I'm wondering if I can dynamically embed fonts in Flex. I want to embed different fonts for different users so I don't want to embed all possible fonts in the same Flex file. If it's possible could you please post sample code.
You can do this in Actionscript. I've used this trick primarily to use opentype fonts that weren't supported with the compiler in the Flash IDE and to create font libraries that could be loaded lazily (only when needed), but you can also use this to selectively load fonts. If you had the mxmlc compiler on your server you could even generate the fontlib.as file and compile it on command.
// fontlib.as
// font library file
package {
import flash.display.Sprite;
public class fontlib extends Sprite {
[Embed(source = 'font/path/FontFile.otf', fontName = 'FontFile', unicodeRange = 'U+0020-U+007E,U+00AB,etc...')]
public static var FontFile:Class;
public static const FontFile_name:String = "FontFile"; // matches 'fontName' in embed
public function fontlib() {
}
}
}
This can be compiled like so:
mxmlc fontlib.as
You can use in your application like this:
// Main.as
// document class
package {
import flash.text.Font;
import flash.display.Loader;
import flash.events.Event;
import flash.system.ApplicationDomain;
import flash.text.StyleSheet;
public var fontsLoader:Loader;
public var fontFile:String = "";
public var ss:StyleSheet;
public function Main() {
fontsLoader = new Loader();
fontsLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, _onFontsLoadComplete);
}
private function _onFontsLoadComplete(e:Event):void {
var fontlib:Class = e.target.applicationDomain.getDefinition('fontlib');
Font.registerFont(fontlib.FontFile); // registers font
fontFile = fontlib.FontFile_name; // name the font was loaded as
// actually using the font looks like this:
ss = new StyleSheet();
ss.parseCSS("div { fontFamily: " + fontFile + "; }");
}
}
Related
This code compile in Intellij, but it does not work in jar.
Working with getResourceAsStream() or getResource doest not solve the problem.
(I have tried out with Image like Image image = newImage(getClass().getResourceAsStream("image.png");and it does work)
package Sound;
import javafx.application.Application;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.io.File;
/**
*/
public class TestSound extends Application{
public TestSound() {
play();
}
#Override
public void start(Stage primaryStage) throws Exception {
new TestSound().play();
}
private void play(){
String mainsound = "src/res/sound/main.mp3";
Media i = null;
i = new Media( new File(mainsound).toURI().toString());
MediaPlayer mediaPlayer = new MediaPlayer(i);
mediaPlayer.play();
mediaPlayer.setStopTime(new Duration(120000));
mediaPlayer.setCycleCount(MediaPlayer.INDEFINITE);
}
public static void main (String[] args){
launch(args);
}
}
EDIT:
Media i = new Media(getClass().getClassLoader().getResource(mainsound));
wont work, because the constructor need a String.
but also
Media i = new Media(getClass().getClassLoader().getResource(mainsound).toString());
new MediaPlayer(i).play();
does not work.
ofcourse mainsound="res/sound/main.mp3";
After extraction of jar with winrar
I got dictionary of sound with include the
testsound.class and main.mp3
And another dictionary of res with include main.mp3
Both dictionary are in the same root.
getClass().getResource("res/sound/main.mp3") is going to look for a resource named res/sound/main.mp3 relative to the current class. Since your class is in the sound package, it's effectively going to look for /sound/res/sound/main.mp3, which is not where the resource is located in your jar.
If the list of entries in the jar file is showing
/sound/main.mp3
then the following should work:
String mediaURL = getClass().getResource("/sound/main.mp3").toExternalForm();
// for debugging:
System.out.println(mediaURL);
Media i = new Media(mediaURL);
Instead of using getClass ().getResource (...) it would be ideal to use it like
Media m = new Media ("/myMedia.mp3");//if the media exists in default package
or
Media m = new Media ("/mypackage/myMedia.mp3");//if the media exists in mypackage
I have a window application that i have developed in flex sdk 4.6 . I have the same version in web based application. In this application i am loading external swf font file. In web application everything is working fine but font is not loaded in window application.
Below is the code for loading the fonts..
package com
{
import adobe.utils.CustomActions;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IOErrorEvent;
import flash.net.URLRequest;
import flash.text.Font;
import injectors.CentralInjector;
import mx.core.FontAsset;
public class LF extends EventDispatcher
{
public function LF()
{
}
public function avaliable(style:String):Boolean{
var embeddedFonts:Array = Font.enumerateFonts(false);
for(var i:Number = 0; i < embeddedFonts.length; i++){
var item:Font = embeddedFonts[i];
if(item.fontStyle==style){
return true;
}
}
return false;
}
public function load(url:String):void{
//=====url is http://www.mydomain.com/font1.swf=================
CustomWaitAlert.show(CustomWaitAlert.WAIT,null,"Loading fonts...");
var loader:Loader = new Loader();
var loaderInfo:LoaderInfo = loader.contentLoaderInfo;
loaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioerror);
loaderInfo.addEventListener(Event.COMPLETE, onLoadComplete);
loader.load(new URLRequest(url));
}
private function ioerror(evt:IOErrorEvent):void{
this.dispatchEvent(new Event("IOERROR"));
}
private function onLoadComplete(evt:Event):void{
var embeddedFonts:Array = Font.enumerateFonts(false);
this.dispatchEvent(new Event("COMPLETE"));
CustomWaitAlert.hide();
}
}
}
The solution i got is to first load the font swf via url loader then we get the bytearray.after that just load tge bytearray with the loader class with loading context which is having allowcodeimport sets to true...
This is a really strange one. I've created my own CustomTextField class which I am using to embed the font and set the defaultTextFormat. This is working absolutely fine, but for some reason when I try to create a new CustomTextField in any module but the parent application, text text is only showing sometimes.
Here is my CustomTextField class:
package uk.package.text
{
import flash.text.AntiAliasType;
import flash.text.Font;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
public class CustomTextField extends TextField
{
[Embed(source='../assets/fonts/Arial.ttf',fontName='CustomFont',fontWeight='regular',
unicodeRange='U+0020-U+0040,U+0041-U+005A,U+005B-U+0060,U+0061-U+007A,U+007B-U+007E,U+0080-U+00FF,U+0100-U+017F,U+0400-U+04FF,U+0370-U+03FF,U+1E00-U+1EFF',
mimeType='application/x-font-truetype'
)]
public static var MY_FONT:Class;
[Embed(source='../assets/fonts/Arial Bold.ttf',fontName='CustomFont',fontWeight='bold',
unicodeRange='U+0020-U+0040,U+0041-U+005A,U+005B-U+0060,U+0061-U+007A,U+007B-U+007E,U+0080-U+00FF,U+0100-U+017F,U+0400-U+04FF,U+0370-U+03FF,U+1E00-U+1EFF',
mimeType='application/x-font-truetype'
)]
public static var MY_FONT_BOLD:Class;
public static const DEFAULT_FONT:String = "Arial";
public static const DEFAULT_TEXT_COLOUR:int = 0x000000;
public static const DEFAULT_TEXT_SIZE:int = 14;
private var _tf:TextFormat = new TextFormat(DEFAULT_FONT, DEFAULT_TEXT_SIZE, DEFAULT_TEXT_COLOUR);
public function CustomTextField():void
{
var CustomFont:Font = new MY_FONT();
_tf.font = CustomFont.fontName;
_tf.size = 16;
embedFonts = true;
antiAliasType = AntiAliasType.ADVANCED;
defaultTextFormat = _tf;
autoSize = TextFieldAutoSize.LEFT;
}
public override function set htmlText(value:String):void
{
super.htmlText = value;
setTextFormat(_tf);
}
public function get textFormat():TextFormat
{
return _tf;
}
}
}
It's weird how sometimes it works and sometimes it doesn't... perhaps there is something odd going on with the modules?
Ok, this one took me ages to figure out. I finally got it working by using the following code:
preinitialize="moduleLoader.moduleFactory=Application.application.systemManager;"
In the module loader item.
Thanks!
yes it's almost definitely a module issue. I've seen something similar before. I'm searching out the answer but my initial thought is to set
moduleLoader.applicationDomain = ApplicationDomain.currentDomain
Another issue is if you're loading the same module twice. If so you need to make the url unique by adding file.swf?<randomNumber> or something similar.
I want to load an swf into a flex 4 application in order to use its classes.
var ldr:Loader=new Loader();
ldr.load(new URLRequest("file://path/to/fileswf"));
ldr.contentLoaderInfo.addEventListener(Event.INIT, loaded);
function loaded(evt:Event):void { addChild(ldr); }
I receive the error:
Error: addChild() is not available in this class. Instead, use addElement() or modify the skin, if you have one.
at spark.components.supportClasses::SkinnableComponent/addChild()[E:\dev\gumbo_beta2\frameworks\projects\spark\src\spark\components\supportClasses\SkinnableComponent.as:966]
at main/private:init/loaded()[C:\Documents and Settings\ufk\Adobe Flash Builder Beta 2\xpogames-toolkit-test\src\main.mxml:22]
If I change addChild() to addElement(), I receive the following compilation error:
1067: Implicit coercion of a value of type flash.display:Loader to an unrelated type mx.core:IVisualElement. main.mxml path/dir line 22 Flex Problem
Any ideas how to resolve this issue?
Create another container to place the displayObject in:
// container ( IVisualElement ) for DisplayObjects
var container:UIComponent = new UIComponent();
addElement( container );
// displayObject goes to container
var displayO:Sprite = new Sprite();
container.addChild( displayO );
well in flash builder 4 full version, there isn't any this.rawChildren.
The best approach to resolve the issue would be to convert each required class to a flex component and to use it on your flex application:
download and install flex component kit
http://www.adobe.com/cfusion/entitlement/index.cfm?e=flex_skins
create a movie clip
convert to flex component
add the relevant functions to this class
a skeleton for a class that is attached to a movieclip that is about to be converted to a flex component:
package {
import mx.flash.UIMovieClip;
import flash.text.TextField;
import flash.events.Event;
import flash.events.MouseEvent;
public dynamic class challenge_screen extends UIMovieClip {
public function challenge_screen() {
super();
}
}
}
this.rawChildren.addChild( ldr )
should work
private var _loader:SWFLoader = new SWFLoader();
private var _uicomponent:UIComponent = new UIComponent();
private function swfLoaded(event:Event):void
{
Alert.show("inside swf Loaded");
var content:DisplayObject =_loader.content;
_uicomponent.addChild(content);
}
public function loadSWF () : void
{
_loader.addEventListener(Event.INIT, swfLoaded);
_loader.load("http://intelliveysoft.com:5080/myelearn/Admin.swf");
addElement(_uicomponent);
}
Try this. It will work
I have a very simple practice program for Flex 4 ( Gumbo ).
package
{
import mx.controls.ColorPicker;
import mx.controls.Label;
import mx.events.ColorPickerEvent;
import flash.display.Sprite;
public class testClass extends Sprite
{
private var cPicker:ColorPicker = new ColorPicker();
private var lbl:Label;
public function testClass()
{
cPicker.addEventListener(ColorPickerEvent.CHANGE,
colorPicker_change);
cPicker.move(10, 10);
addChild(cPicker);
lbl = new Label();
lbl.text = cPicker.hexValue;
lbl.move(10, 40);
addChild(lbl);
}
private function colorPicker_change(evt:ColorPickerEvent):void
{
lbl.text = cPicker.hexValue; // ff0000
}
}
}
But after building with 'mxmlc.exe testClass.as' on the command line, I get...
C:\src>mxmlc testClass.as Loading configuration file
C:\flex_sdk_4\frameworks\flex-config.xml
C:\src\testClass.as(21): col:
32 Error: Access of possibly undefined
pro perty hexValue through a reference
with static type
mx.controls:ColorPicker.
lbl.text = cPicker.hexValue;
^
C:\src\testClass.as(28): col:
32 Error: Access of possibly undefined
pro perty hexValue through a reference
with static type
mx.controls:ColorPicker.
lbl.text = cPicker.hexValue; // ff0000
^
Why does it think that cPicker is static? Or that cPicker.hexValue is undefined?
Also it seems that even after importing the ColorPicker library in the code using the import keyword, I somehow have to import it on the commandline for building as well. Is that correct?
According to my reading of the documentation hexValue isn't a property available on the ColorPicker. Do you mean selectedColor?