sIFR vs. cufón: Text replacement and you

by JamesDiacono 31. March 2010 10:40

There are two reasons I use dynamic text replacement:

  1. Plain text in a browser window is never as smooth as it is in the design (except in Safari),
  2. The designs I'm given almost always use fancy (non-web based) fonts for headings, intro text etc.

Currently I subscribe to two solutions, both client-side: sIFR and cufón. If you want a quick answer to "what should I use?" then here it is: if you want replacement for long sentences and headings, use sIFR. If you want replacement for a few words on a button or in a menu, use cufón. If you want to know more, read on...

sIFR

How sIFR works

sIFR uses javascript to dynamically embed a Flash object in the place of specified HTML text elements. The Flash object is essentially an empty SWF (compiled Flash file) which includes the characters of the font you want to use. When javascript embeds the SWF in the HTML, it passes the SWF arguments such as text-content, font-size, color, rollover behaviour and many more. Some of these properties javascript takes from the CSS applied to the text, and some are overridden by sifr-config.js, which is a human-readable config file containing additional formatting tweaks.

How to use sIFR

  1. Download the source (only sifr.js, sifr-config.js and sifr.css are actually needed).
  2. Generate a font SWF from a True Type Font file. You can do this manually with Adobe Flash (like this) but it is easier to use this online generation tool.
  3. Link to sifr.css in the head of your HTML page.
  4. Link to both scripts in the head of your HTML page, first sifr.js, then sifr-config.js
  5. Edit sifr-config.js to read in the font SWF you created and use CSS selector syntax to select the HTML text elements you want to replace.
  6. Tweak away in sifr-config.js until the text looks right when sIFR is both enabled and disabled, in case the user is missing Flash (iPhones don't have Flash as of early 2010!).

cufón

How cufón works

cufón is entirely javascript and works in all major browsers (including IE6). You still need to generate a font file, but this is output to a javascript file similar in size to the equivalent sIFR SWF font file. cufón looks at selected blocks of text and replaces each word with a dynamically generated image (using the HTML <canvas> tag), or in IE's case, a VML object (Vector Markup Language). As a consquence of this, increasing the text size of the page either doesn't affect cufón-replaced text or expands the image, blurring it. Except in IE, which scales the text perfectly.

How to use cufón

  1. Download the source (all you need is cufon-yui.js)
  2. Generate a font file from a True Type Font. You are unfortunately dependent on this online generator.
  3. Link to cufon-yui.js in the head of your HTML page. Beneath it, link to any font files you've generated.
  4. You may also want to create another file, cufon-config.js, to hold selector information much the same way as sifr-config.js does.
  5. Populate cufon-config.js with what HTML text elements you want to replace.

Legality

Font foundaries are seemingly run by people who are very freaked out that their fonts are going to leak for free. Hence, the vast majority of fonts can't legally be embedded directly into the CSS (what, you didn't know about that? It's been around a while in some form or another - the @font-face directive allows you to supply the font file for obscure font-families - but it's only legal with open source fonts).

Because sIFR uses Flash, and Adobe has a cordial agreement with the font foundaries in Switzerland (or wherever) which allows anyone to embed pretty much any font in a .swf, sIFR is totally legal. cufón... cufón not so much. Although both supply a compiled/obfuscated font resource in .swf/.js format respectively, and are basically the same from the font foundaries' point of view, they haven't got around to adding "Allows embedding using javascript methods" to their fonts' terms of use agreements. And I wouldn't count on it...

So in short, use cufón. Go on, it's young and fresh and rad! Push the font foundaries to legalise it! But remember: you read that in a blog post...I'm not going to be your lawyer if they come after you.

Comparison

sIFR cufón
Core file-size (not including fonts) 30KB 18KB
Independent of Flash ×
Resizes nicely ×
Cursor-selectable text ×
Doesn't flicker on load ×
Independent of online font-generator ×
Online font-generator supports Open fonts (.otf) ×
Supported in all browsers
Degrades gracefully
Legal ×
Categories: Flash | JavaScript

More on Umbraco, TinyMCE and Flash

by Aaron Powell 3. February 2010 10:05

In a previous post Shannon explained how to customise TinyMCE for what HTML elements Flash actually supports, and he finished off the post with showing how to cleanup line breaks.

To do this he used an XSLT function called normalize-space, which is great if you’re using XSLT!

I was writing a service today which was using LINQ to XML to generate the XML for Flash, but that posed a problem, how do you deal with Flash wanting to do hard breaks on new line constants?

Easy, string.Replace to the rescue!

Here’s a handy little extension method you can drop into your code libraries:

public static string NormalizeSpace(this string s) {
	if(s == null) throw new ArgumentNullException("s");
	return s.Replace("\r\n", string.Empty)
		.Replace("\r", string.Empty)
		.Replace("\n", string.Empty);
}

Nice and easy (and unsurprisingly logical!).

Categories: .Net | Flash | Umbraco

Umbraco TinyMCE Customization for Flash Rich Text

by Shannon Deminick 7. January 2010 08:15

Flash doesn’t support most of the html elements of a standard web page. TinyMCE’s creators Moxiecode have thankfully given us the TinyMCE rules for flash here:

http://wiki.moxiecode.com/index.php/TinyMCE:Configuration/valid_elements#Full_FlashMX_2004_rule_set:

So to get Umbraco & TinyMCE working to give your flash application the markup that it needs you need to modify your \config\tinyMceConfig.config file:

<validElements>
    <![CDATA[+a[href|target],
+b,
+br,
+font[color|face|size],
+img[src|id|width|height|align|hspace|vspace],
+i,
+li,
+p[align|class],
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+span[class],
+textformat[blockindent|indent|leading|leftmargin|rightmargin|tabstops],
+u
]]>
</validElements>

Then there’s the issue that flash treats real line breaks and <br/> tags exactly the same! This will probably cause you a few headaches trying to work that out. So to save you that headache, you need to output the rich text markup via XSLT to flash using the XSLT function: normalize-space

Something like:

<xsl:value-of select="normalize-space($myRichTextValue)" />
Categories: .Net | Umbraco | Flash

Introducing Sodality

by Tom Byrne 5. May 2009 05:38

Sodality is a runtime AOP (Aspect Oriented Programming) library for ActionScript 3. Simple implementations of Sodality use Metadata to call functions at specific times. Because of this, simple usage is only possible in IDEs that allow custom Metadata (e.g. Flex, FDT, FlashDevelop, etc), although it can be used in a more advanced manner in Flash (and others which don’t allow custom Metadata).

Simply put, Sodality is like an event system, allowing functions to get called in any part of your application when another piece of code dispatches an Advice object.

  1. Basic Example
  2. Basic Concepts
  3. Simple Usage
  4. A Real Example
  5. Further Flexibility
  6. Download Source

1. Basic Example

If somewhere within your app an Advisor class (more on that soon) dispatched a MouseClickAdvice object (for example), like this:

	dispatchEvent(new MouseClickAdvice(this, mouseX, mouseY));

Any other Advisor could catch the MouseClickAdvice like this (the bracketed metadata is what does the magic):

	[Trigger(timing="before")]
public function onMouseClickAdvice(cause:IMouseClickAdvice):void{
trace("Something was clicked at: "+cause.mouseX,cause.mouseY);
}

Or, it could catch the MouseClickAdvice asynchronously (allowing it to take some time before any other Advisors catch the advice) like this:

	private var advice:AsyncMethodAdvice;

[Trigger(timing="before")]
public function onMouseClickAdvice(cause:IMouseClickAdvice,
advice:AsyncMethodAdvice):void{
/* The advice has been caught here, I'm going
to wait 1 second before allowing it to continue.*/
this.advice = advice;
var timer:Timer = new Timer(1000,1);
timer.addEventListener(TimerEvent.TIMER, onTimer);
}
public function onTimer(event:TimerEvent):void{
trace("I'll now allow the advice to continue");
advice.adviceContinue();
}

2. Basic Concepts

The President

Every Sodality Application has (at least) one President, the President monitors and arranges all Sodality processes. Whilst the president doesn’t get used directly by your code to give Sodality the scope of it’s operations. The President must have a reference to some top level DisplayObject, this allows it to detect Advisors being added or removed from the app, usually this is set to the root of your app.

The Advisors

Any class can become an Advisor by implementing the IAdvisor interface, this allows it to specify Metadata above it’s functions telling Sodality when to call the function. In most apps, IAdvisor is only implemented by DisplayObjects which get added to the stage, non-visual advisors normally extend the DynamicAdvisor class, which allows them to be easily added to the President.

The Advice

Each Advice object represents an operation which will be executed, Advice objects are dispatched like events from any IAdvisor. Normally, each type of request will have an interface associated with it, the Advisors then will listen for the interface (rather than the class) which allows any Advice class to implement as many of these request types as required.

3. Simple Usage

Normally, Sodality is used for broad-scale communication between parts of an application. There are reusable DynamicAdvisors which specify several Advice interfaces allowing your app to instruct the DynamicAdvisor how to behave.

A good example of this would be the SoundAdvisor, which is used to play sounds, adjusting each sound’s volume appropriately and making sure the wrong sounds do not overlap. The SoundAdvisor specifies many Advice interfaces (e.g. IAddSoundAdvice, IRemoveSoundAdvice, IChangeVolumeAdvice, etc.), each of these correspond to a method within the SoundAdvisor. When an Advice object that implements one of these interfaces gets dispatched from another Advisor the SoundAdvisor’s corresponding method will be called and it will have an opportunity to make the required changes (e.g. begin playing a sound, adjust the volume etc.). These Advice interfaces can specify any functions or getters that the SoundAdvisor requires to complete the request, for example, the IChangeVolumeAdvice could look something like this:

package examplePackage
{
import org.farmcode.sodality.advice.IAdvice;

public interface IChangeVolumeAdvice extends IAdvice
{
function get volume(): Number;
function get muted(): Boolean;
}
}

This means that whenever an Advice object implements the IChangeVolumeAdvice interface, it must specify a volume and whether the SoundAdvisor should be muted, which is all the information that the SoundAdvisor needs to complete the request. The reason that interfaces are used instead of classes is so that each Advice object can implement many different interfaces, which will each execute different requests across different Advisors.

4. A Real Example

Stay tuned, we’ll be posting a real example with source code very soon.

5. Further Flexibility

Sodality has been built to be flexible, there are still unexplored pieces of flexibility within it’s architecture, we’d love to see how other people use Sodality and where it goes from here. These are some examples of under-explored areas in Sodality:

IAdviceTrigger

IAdviceTriggers are the object which tie pieces of advice together, they’re a powerful tool which is usually hidden from view, they can dramatically change the functionality of Sodality.

President Monitors

Because of the Asynchronous way that Sodality runs, classes which affect/monitor the running of Sodality can easily be plugged in. Here are some examples of tools we’ve built on to this:

  • A (faux) threading system, which allows different advice streams to take up different amounts of processing time.
  • A step-through debugger
  • A hot-key which traces out any currently pending advice.

Whilst we haven’t open-sourced these, they are good examples of the types of options that are available.

6. Download Source

 

Categories: Flash | Sodality

Tutorial 1: Introducing SiteStream

by Tom Byrne 1. May 2009 11:27

This is part one of a three part tutorial.

SiteStream is an AS3 library for parsing XML into first-class objects. All the information needed for the parsing process is in the XML syntax and there is no need to write any additional code.
XML data sources can reference each other, allowing data to load in piece by piece depending on what your flash app requires.
SiteStream also has the powerful feature of being able to specify other SWFs which contain the classes used, so that your class libraries are loaded invisibly only when required.

  1. Simple XML Syntax Example
  2. Retrieving an item
  3. Download Source

1. Simple XML Syntax Example

SiteStream XML allows you to write object structures in XML format. Each XML Node represents an Actionscript object.

Look at the first child tag in the XML below, it has the following characteristics:

  • It’s node name “Shape” is the name of the Class which will be used for this object
  • It’s namespace “displayPackage” is a package identifier, all package identifiers have a listing in the root tag which specifies the full package for the class.
  • It has an attribute “id” with the value “mask”, this specifies both the property of the parent object that this object should fill and the SiteStream name used in SiteStream paths.
  • It has an attribute “alpha” with a value “0.5”, this is how simple properties are set into objects.

This example creates a Sprite, it then creates a Shape and sets it as the Sprite's mask, then it creates a Rectangle (100x100) which it sets as the Shape's scrollRect.

<displayPackage:Sprite id="root"
displayPackage="flash.display.*"
geomPackage="flash.geom.*"
>
<displayPackage:Shape id="mask" alpha="0.5">
<geomPackage:Rectangle id="scrollRect" x="0" y="0" width="100" height="100"/>
</displayPackage:Shape>
</displayPackage:Sprite>

2. Retrieving an item

The following example has an XML data source which creates an array of MyClass objects (an arbitrary class as an example), the code shows how an item could be retrieved from the array. Notice that the class must be included in the code (more on that in Part 2). The MyClass Class can be seen at the bottom of this post.

myXML.xml:

<Array id="root"
myPackage="myPackage.*">
<myPackage:MyClass id="item1"/>
<myPackage:MyClass id="item2"/>
<myPackage:MyClass id="item3"/>
<myPackage:MyClass id="item4"/>
<myPackage:MyClass id="item5"/>
</Array>

SiteStreamTest.as:

package
{
import org.farmcode.siteStream.SiteStream;
import flash.display.Sprite;
import myPackage.MyClass;
public class SiteStreamTest extends Sprite
{
public function SiteStreamTest(){
var includeClass:Class = MyClass;
var siteStream:SiteStream = new SiteStream();
siteStream.rootURL = "myXML.xml";
siteStream.getObject("root/item2",onSuccess);
}
private function onSuccess(e:MyClass):void{
trace("Item 2 retrieved");
}
}
}


MyClass.as:

package myPackage
{ public class MyClass { public var colour:Number; public var childObject:MyClass; } }

 

3. Download Source


Goto Tutorial 2 >

Categories: Flash | SiteStream

AS3 Cylinder Renderer

by Shannon Deminick 2. June 2008 05:43

  A tiny bit of research into rendering cylinders in actionscript (using a displacement filter) has resulted in this example.

For the sake of anyone out there who is interested in building a renderer for PV3D (or any of the AS3 3D engines) I have included the class code (it won't compile without our supporting libraries, but it will give you an idea how it's done).

Categories: Flash