/*=: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; } } }