Font embedding has been a problem in the past with Flash. I believe now most of the issues are fixed, though it is useful to set up TextFields using best practices.

On the deleteaso blog, some JSFL code was posted that fixed various font embedding issues. This was a response to Seb Lee-Delisle’s idea of fixing fonts using AS3. Though using JSFL is an excellent idea, and the deleteaso code does work, it is pretty bad code:

  • an extra while loop (j-loop), which slows everything down. Fix: removed the loop.
  • a mis-placed if-statement; the code cannot get to the “static” if-statement via the code provided. Fix: break apart the if-statement.
  • should combine all matrix manips into one. Fix: None. I did not change this, since I do not want to debug/test it.
  • should scan all objects in the library that can contain other objects (it only scans MovieClips). Fix: add check for other DisplayObject types. Since I don’t use “button” item type, I only have added/tested the “graphic” item type. The other possible types are: “undefined”, “component”, “movie clip”, “graphic”, “button”, “folder”, “font”, “sound”, “bitmap”, “compiled clip”, “screen”, or “video”.
  • it is not ideal to switch static TFs to dynamic as a default condition. Fix: added a flag and continue-statement to control that feature.
  • very limited feedback for the user, and few comments within the file. Fix: obvious.
  • not sure why a while-loop was used instead of a for-loop. Fix: none . . . not a big deal

Further, I wanted to add an improvement that allowed setting TextField defaults in all open FLA documents, not just one. This is the loop at the top of the code.

If you use this code, note that it only affects TextFields found within the library. This will miss any TFs put directly on the stage – at this point, I have not changed that functionality.

// This code modified by Delfeld, copyright 2009.
// Modified code found at: https://delfeld.wordpress.com/2009/12/01/jsfl-textfield-fix/
// Original code found at: http://deleteaso.com/fix-textfields-jsfl/

fl.outputPanel.clear();

//scanLibrary(fl.getDocumentDOM().library);

var doChangeStaticToDynamic = false;
var outStr = "Fixing textfields for proper output.\nNOTE: This will only affect objects held in the library (or instances of them).\n\n";
var testDoc;

// cycle through all open documents:
for (doc in fl.documents)
{
    outStr += "Document: " + fl.documents[doc].name + "\n";
    
    // set TextField defaults in this doc:
    scanLibrary(fl.documents[doc].library);
}

fl.trace( outStr );

// -------------------------------------------------------

// auxillary function:
function getIsWholeInt(n)
{
    var s = String(n);
    if(s.indexOf(".") != -1)
    {
        return false;
    }
    else
    {
        return true;
    }
}

// auxillary function:
function round(n)
{
    var s = String(n);
    var a = s.split(".");
    var num = parseInt(a[0]);
    var dec = parseInt(a[1].substr(0, 1));
    if(dec >= 5)
    {
        num++;
    }
    return num;
}

/**
 * Scans the supplied flash library for linked classes and makes sure the textfields are set up properly
 * @param   library     A flash library to scan.
 */
function scanLibrary(library)
{
    // outStr += "Scanning textfields";
    
    // loop variables:
    var item, timeline, layerCnt, frameCnt, elems, elemCnt, matX, tx, matY, ty;
    
    var items = library.items;
    var replaceCount = 0;
    
    // for each item in the library:
    for( var i = 0; i < items.length; i++ )
    {
        item = items[i];
        
        //outStr += "item: " + item.itemType + "\n"
        
        // dig into any MCs:
        if (item.itemType == 'movie clip' || item.itemType == 'graphic' )
        {
            // store current timeline:
            timeline = item.timeline;
            
            // store total number of layers:
            layerCnt = timeline.layerCount;
            
            // set up editing mode:
            library.selectItem(item);
            library.editItem();
            
            // cycle through all layers within this timeline:
            while(layerCnt--)
            {
                // store total frames
                frameCnt = timeline.layers[layerCnt].frameCount;
                
                // cycle through all frames within this layer:
                while(frameCnt--)
                {
                    // store elements array:
                    elems = timeline.layers[layerCnt].frames[frameCnt].elements;
                    
                    // store total number of elements in this frame:
                    elemCnt = elems.length;
                    
                    // cycle through all elements within this frame:
                    while(elemCnt--)
                    {
                        // process any text type element:
                        if( elems[elemCnt].elementType == "text" )
                        {
                            outStr += "\t Found a textfield: "
                            + ((elems[elemCnt].name == "&quot😉 ? "{no name}" : elems[elemCnt].name);
                            
                            //Change the static TextFields to dynamic
                            if( elems[elemCnt].textType == "static" )
                            {
                                if( !doChangeStaticToDynamic )
                                {
                                    outStr += ".  Ignoring this static TextField.\n";
                                    //skip this iteration (element)
                                    continue;
                                }
                                else
                                {
                                    outStr += ". (Switching this static TextField type to dynamic.)\n";
                                    // change text type to dynamic:
                                    elems[elemCnt].textType = "dynamic";
                                }
                            }
                            
                            outStr += "\t Text type: " + elems[elemCnt].textType + "\n";
                            
                            if(elems[elemCnt].textType == "dynamic&quot😉
                            {
                                //Remove the ability to be selectable
                                elems[elemCnt].selectable = false;
                            }
                            
                            // This section applies to all dynamic or input TextFields
                            
                            // Remove the auto kern attribute
                            elems[elemCnt].setTextAttr('autoKern', false);
                            
                            // Embed fonts UpperCase, LowerCase, Numerals, Punctuation
                            // This can be fine tuned to get a smaller font set.
                            elems[elemCnt].embedRanges = "1|2|3|4";
                            
                            // Pop onto whole pixel
                            // not sure that two assignments are needed:
                            matX = elems[elemCnt].matrix;
                            tx = matX.tx;
                            if(!getIsWholeInt(tx))
                            {
                                matX.tx = round(tx);
                                elems[elemCnt].matrix = matX;
                            }
                            // Can this be combined with the 'x' section?
                            matY = elems[elemCnt].matrix;
                            ty = matY.ty;
                            if(!getIsWholeInt(ty))
                            {
                                matY.ty = round(ty);
                                elems[elemCnt].matrix = matY;
                            }
                        }
                    }
                }
            }
        }
    }
}

– 30 –

Advertisements