/*=:project
scalable Inman Flash Replacement (sIFR) version 3.
=:file
Copyright: 2006 Mark Wubben.
Author: Mark Wubben,
=:history
* IFR: Shaun Inman
* sIFR 1: Mike Davidson, Shaun Inman and Tomas Jogin
* sIFR 2: Mike Davidson, Shaun Inman, Tomas Jogin and Mark Wubben
=:license
* This software is licensed and provided under the CC-GNU LGPL
* See
*/
import Word;
import Line;
import SifrStyleSheet;
class sIFR {
public static var DEFAULT_TEXT = '8:Rendered,4:with,4:sIFR,1:3';
public static var CSS_ROOT_CLASS = 'sIFR-root';
public static var DEFAULT_WIDTH = 300;
public static var DEFAULT_HEIGHT = 100;
public static var MARGIN_LEFT = -3;
/* public static var MARGIN_TOP = -5;*/
public static var MAX_FONT_SIZE = 126;
public static var ALIASING_MAX_FONT_SIZE = 48;
public static var LINEBREAK = ' \r';
public static var styles = new SifrStyleSheet();
public static var fromLocal = false;
public static var domains = [];
private static var links;
private static var targets;
private var textField;
private var originalHeight;
private var currentHeight;
public static function setDefaultStyles() {
sIFR.styles.parseCSS([
'.', CSS_ROOT_CLASS, ' { color: #000000; }',
'strong { display: inline; font-weight: bold; } ',
'em { display: inline; font-style: italic; }',
'a { color: #0000FF; text-decoration: underline; }',
'a:hover { color: #0000FF; text-decoration: none; }'
].join(''));
}
public static function checkDomain() {
if(sIFR.fromLocal) sIFR.domains.push('localhost');
var domain = (new LocalConnection()).domain();
for(var i = 0; i < sIFR.domains.length; i++) {
if(sIFR.fromLocal && sIFR.domains[i] == "*"
|| sIFR.domains[i] == domain) {
return true;
}
}
return false;
}
public static function run(holder, parsedContent, chars) {
if(!checkDomain()) return;
// Sets stage parameters
Stage.scaleMode = 'noscale';
Stage.align = 'TL';
Stage.showMenu = false;
// Other parameters
holder._alpha = 100;
// Parse CSS
sIFR.styles.parseCSS(_root.css);
// Parse links and targets
sIFR.links = _root.links.split(',');
sIFR.targets = _root.targets.split(',');
var sifr = new sIFR(holder.txtF, parsedContent, chars);
_root.onEnterFrame = function() {
sifr.onEnterFrame();
};
return sifr;
}
public static function followLink(index) {
var href = unescape(sIFR.links[index]);
var target = unescape(sIFR.targets[index]);
getURL(href, target);
}
private static function getRatio(size) {
if(size <= 10) return 1.55;
if(size <= 19) return 1.45;
if(size <= 32) return 1.35;
if(size <= 71) return 1.30;
return 1.25;
}
private function sIFR(textField, parsedContent, chars) {
parsedContent = parsedContent || DEFAULT_TEXT;
this.textField = textField;
textField._width = (_root.w || DEFAULT_WIDTH) - MARGIN_LEFT;
textField._x = MARGIN_LEFT;
textField._height = _root.h || DEFAULT_HEIGHT;
/* textField._y = MARGIN_TOP;*/
textField.wordWrap = false;
// Determine font-size and the number of lines
var fontSize = parseInt(_root.size);
var requiredLines = parseInt(_root.lines);
var extraLines = parseInt(_root.extralines); // extra lines possibly introduced by linebreaks
if(fontSize < ALIASING_MAX_FONT_SIZE) textField.antiAliasType = 'advanced';
// Set font-size and other styles
var rootStyle = styles.getStyle('.sIFR-root') || {};
rootStyle.fontSize = fontSize; // won't go higher than 126!
rootStyle.padding = 0;
styles.setStyle('.sIFR-root', rootStyle);
textField.styleSheet = styles;
// The wrapping algorithm; it appears to work well enough up to more than
// 10 lines, good enough I'd say
// First parse the content: unescape and create a words array
var preparsed = parsedContent.split(',');
chars = chars.split(',');
var words = [];
var breaks = [];
for(var i = 0; i < preparsed.length; i++) {
var word = new Word(unescape(preparsed[i]), parseInt(chars[i]));
if(word.breaks()) breaks.push(word);
words.push(word);
}
var content = [];
requiredLines = Math.min(words.length, requiredLines);
var lines = [new Line];
if(requiredLines == 1) {
lines[0].pushAll(words);
} else {
var sliceSize = Math.round(words.length / (requiredLines - 1));
var actualSlice;
for(var i = 0; i < requiredLines; i++) {
actualSlice = sliceSize;
if(requiredLines == 2 && i == 0 || i == requiredLines - 2) {
actualSlice = 2;
if(sliceSize > 4) actualSlice = sliceSize - 2;
if(words.length == 2) actualSlice = 1;
} else if(i == requiredLines - 3) actualSlice = sliceSize - 1;
else if(i == requiredLines - 1) actualSlice = words.length;
if(!lines[i]) lines[i] = new Line;
lines[i].pushAll(words.splice(0, actualSlice));
}
}
// balance out lines according to character length
for(var i = 0; i < lines.length - 1; i++) {
var currentLine = lines[i];
var nextLine = lines[i + 1];
if(i == lines.length - 1) {
while(currentLine.length < nextLine.length) {
currentLine.unshift(lines[i-1].pop());
}
} else {
while(currentLine.chars < nextLine.chars) {
currentLine.push(nextLine.shift());
}
}
}
// take care of line breaks
for(var i = 0; i < breaks.length; i++) {
var word = breaks[i];
word.removeBreak();
var line = word.line;
var wordIx = 0;
while(wordIx < line.words.length) {
if(line.words[wordIx] == word) break;
wordIx++;
}
if(wordIx == 0) {
line.forceBreak = true;
continue;
}
var lineIx = 0;
while(lineIx < lines.length) {
if(lines[lineIx] == line) break;
lineIx++;
}
var nextLine = lines[lineIx + 1];
if(!nextLine) nextLine = lines[lineIx + 1] = new Line;
nextLine.unshiftAll(line.spliceEnd(wordIx));
nextLine.forceBreak = true;
var prevLine = lines[lineIx - 1];
if(extraLines > 0 && prevLine && !line.forceBreak
&& prevLine.chars + line.chars < nextLine.chars) {
prevLine.pushAll(line.spliceEnd(0));
lines.splice(lineIx, 1);
extraLines--;
}
}
this.write(lines);
// Detect if we need to wrap some words
while(textField._width - MARGIN_LEFT < textField.textWidth) {
var maxWidth = 0;
var currentLine, nextLine, ix;
for(var i = 0; i < lines.length; i++) {
this.write([lines[i]]);
if(textField.textWidth > maxWidth) {
currentLine = lines[i];
ix = i;
maxWidth = textField.textWidth;
}
}
// If the line contains just one word, resize the movie
// Perhaps make this an option?
if(currentLine.words.length == 1) {
this.write(lines);
textField._width = textField.textWidth + MARGIN_LEFT;
fscommand('resize', 'width:'+textField._width);
break;
}
// Wrap the last word to the next line
nextLine = lines[ix + 1];
if(!nextLine) nextLine = lines[ix + 1] = new Line;
else if(nextLine.forceBreak) {
nextLine = new Line;
lines.splice(ix + 1, 0, nextLine);
}
nextLine.unshift(currentLine.pop());
this.write(lines);
}
if(lines.length > requiredLines || fontSize == MAX_FONT_SIZE) {
textField._height = Math.round(
(lines.length > requiredLines ? lines.length : requiredLines)
* getRatio(fontSize) * fontSize
);
fscommand('resize', 'height:'+textField._height);
}
/* textField._height += MARGIN_TOP;*/
/* fscommand('resize', 'height:'+textField._height);*/
this.originalHeight = textField._height;
this.currentHeight = Stage.height;
textField._xscale = textField._yscale = parseInt(_root.zoom);
}
private function write(lines) {
this.textField.htmlText = ['
',
lines.join(LINEBREAK), '
'
].join('');
}
public function onEnterFrame() {
if(Stage.height != this.currentHeight) {
this.currentHeight = Stage.height;
var scale = 100 * Math.round(this.currentHeight / this.originalHeight);
textField._xscale = textField._yscale = scale;
}
}
}