Symmetri Developer Blog

October 30, 2007

XML-RPC in PHP

General, PHP, XML - By Shourov Bhattacharya

If you are looking for an implementation of XML-RPC in PHP, I can recommend Keith Deven’s XML-RPC Library for PHP (v 2.5) as an excellent solution. Although the XML-RPC for PHP open source project is more comprehensive and more widely used (I think), the disadvantage that I saw was that it was far too complex to actually use, especially when building the server. Keith Devens’ solution, by contrast, is far cleaner, simpler and easier to understand. And the more software I write, the more I appreciate simplicity as a virtue.

October 25, 2007

Embed With Care

Flash/Flex - By Shourov Bhattacharya

This isn’t anything new, but it’s worth re-iterating if you are new to Flash - be very careful about embedding fonts - it can massively blow out your file size and make your publishing extremely slow. 

Here is an example: in my latest project, I inadvertently embedded the entire character set for Arial at two different point sizes in two dynamic text fields. My size report showed the following:

Font Name                 Bytes        Characters   
———————-    ———    ————–
Arial  11 pts               1617415     !"#$%&’???… [showed all 54665 characters]
Arial   8 pts                  1548     %.0123456789:
Arial  10 pts               1404168     !"#$%&'’???… [showed all 54665 characters]
_sans  10 pts                     6   
verdana  10 pts                 222     CFNPacehilor
_sans                             6   
 

Embedding those two Arial fonts added more than 3MB to the file size! I also noticed that the time it took to publish my project went from a few second up to almost 15 minutes. Of course I removed those embedded fonts pretty quickly. This is what my size report shows now:

Font Name                 Bytes        Characters   
———————-    ———    ————–
_sans  11 pts                    11   
_sans   8 pts                    11   
_sans  10 pts                    11   
_sans                            11   

Really, unless there is a compelling reason for it, NEVER embed all (54665) character glyphs. And use device fonts wherever layout and aesthetics is less important.

October 22, 2007

Simple Actionscript tweener (2)

Flash/Flex, Algorithms - By Shourov Bhattacharya

Here’s a version of the Actionscript tweener function that has a kind of "zoom" effect - the tween accelerates and then eases into the last part.

  // Easing enterframe function for a Movieclip
 public static function easeToTrig(tgt:MovieClip, xps:Number, yps:Number, frames:Number, callback:Object, caller:Object, wps:Number, hps: Number):Void
 {
  arguments.length < 4 ? frames = 10: null;

  var scaleSize:Boolean;
  
  if (arguments.length == 8)
   scaleSize = true;
  else
  {
   wps = tgt._width;
   hps = tgt._height;
   scaleSize = false;
  }

  var ox = tgt._x;
  var oy = tgt._y;
  var ow = tgt._width;
  var oh = tgt._height;

  var dx = (xps - ox);
  var dy = (yps - oy);
  var dw = (wps - ow);  
  var dh = (hps - oh);  
  
  var i = 0;
  
  tgt.onEnterFrame = function()
  {
   i = i + 1;
   var factor:Number =  Math.sin(i*Math.PI/(2*frames));
   
   this._x = ox + (dx * factor);
   this._y = oy + (dy * factor);
   
   if (scaleSize == true)
   {
    this._width = ow + (dw * factor);
    this._height = oh + (dh * factor);   
   }

   
   if (i == frames)
   {
    this._x = xps;
    this._y = yps;

    if (scaleSize == true)
    {    
     this._width = wps;    
     this._height = hps;        
    }
    
    // callback function
    if (callback != null)
    {
     callback.call(caller);
    }
    
    delete this.onEnterFrame;
   }
  };
 }; 

Simple Actionscript tweener

Flash/Flex - By Shourov Bhattacharya

There’s nothing too original or extraordinary about this function, but it’s useful enough to post and maybe save someone else the fifteen minutes needed to write it. You can use it scale and move a movieclip over a given number of frames and then invoke a callback function when done. It’s simple runtime tweening using Actionscript. Very easy to do, and putting it into a generic function like this makes it super-easy to use.

[I have adapted this function from code found in Jeroen Wijering’s Flash Media Player]

class Animations {

// Easing enterframe function for a Movieclip
 public static function easeTo(tgt:MovieClip, xps:Number, yps:Number, frames:Number, callback:Object, caller:Object, wps:Number, hps: Number):Void
 {
  arguments.length < 4 ? frames = 10: null;
  arguments.length < 6 ? wps = tgt._width: null;
  arguments.length < 7 ? hps = tgt._height: null;
  
  var dx = (xps - tgt._x)/frames;
  var dy = (yps - tgt._y)/frames;
  var dw = (wps - tgt._width)/frames;  
  var dh = (hps - tgt._height)/frames;
  var i = 0;
  
  tgt.onEnterFrame = function()
  {
   this._x = this._x + dx;
   this._y = this._y + dy;
   this._width = this._width + dw;
   this._height = this._height + dh;   
   
   if (++i == frames)
   {
    this._x = Math.round(xps);
    this._y = Math.round(yps);
    this._width = Math.round(wps);    
    this._height = Math.round(hps);        
    
    // callback function
    if (callback != null)
    {
     callback.call(caller);
    }
    
    delete this.onEnterFrame;
   }
  };
 };

};

Here’s an example of how to call it:

function setAlpha() { sprite._alpha = 15;}

// move sprite to origin and scale by 50%, then set alpha to 15%

Animations.easeTo(sprite, 0, 0, 12, this.setAlpha, this, sprite._width/2, sprite._height/2);

MakeXml10Safe()

PHP, XML - By Shourov Bhattacharya

I am writing a Web Service that returns data in simple XML 1.0. The character encoding of the data is UTF-8, but writing the XML output, I found that responses were sometimes throwing errors on the XML parser on the client side, with an "Invalid character in XML …" type error (for example, using the XML parser built into Firefox).

It turns out that my data contains a number of control characters that lie outside the range of valid XML 1.0 characters (see http://www.w3.org/TR/REC-xml/#charsets):

Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]

The best solution I found was to write my own "replace" function to convert these characters into character code references:

 /**                                                                
 * Strip out special characters from a string and make it XML 1.0 safe.
 *                                                                  
 * @param string $input, string to clean
 * @return $response, cleaned string
 *
 */  
 function MakeXml10Safe($input)
 {
  // escape common characters
  $output = str_replace(’&’, ‘&amp;’, $input);  
  $output = str_replace(’<’, ‘&lt;’, $output); 
  $output = str_replace(’>’, ‘&gt;’, $output);   
  $output = str_replace(’\n’, ‘’, $output);  
  // escape control codes that are not valid XML 1.0
  $pattern = ‘/[\x-\x8\xb-\xc\xe-\x1f]/’;
  $output = preg_replace($pattern,’&#’.ord(’$0′).’;',$output);
  
  return $output;
 }

October 17, 2007

Use the BLOB

MySQL - By Shourov Bhattacharya

I’ve come across a real "gotcha" when using MySQL 4.0* to store string data. It appears that when using TEXT, VARCHAR or CHAR fields, MySQL does not treat trailing spaces as significant. In other words, the following two queries will always return exactly the same rowset, even though the comparisons are different:

SELECT * FROM table WHERE entry = ‘M’; 

SELECT * FROM table WHERE entry = ‘M ‘;

The MySQL folks insist this isn’t a bug but a known feature (http://bugs.mysql.com/bug.php?id=5412), although I am yet to find an explanation of why they have decided it should be this way. Especially in the case of a TEXT field, where you might expect the comparison would be byte-for-byte. Incidentally, I have found a related problem - often, you can’t query on empty TEXT fields. Even if you have a number of fields in your table that have an empty (zero bytes) TEXT entry field, the following query does not work:

SELECT * FROM table WHERE entry = ‘’

You have to do something else, like this:

SELECT * FROM table WHERE LENGTH(entry)=0

Which is, of course, far uglier and slower as well.

But there is a solution. The trick is to convert your field from TEXT (or VARCHAR) to a BLOB. A BLOB field is similar to a TEXT field, but string comparisons are done more exactly by matching byte values. Comparisons on a BLOB field do NOT ignore trailing spaces. The only caveat is that because it is comparing byte values, string comparisons on a BLOB field are case-sensitive, unlike on a TEXT of VARCHAR field which are case-INsensitive. If you still need a case-insensitive comparison, there is a workaround, however: cast the value to a regular "cased" character set (such as Latin) before comparison:

SELECT * FROM table WHERE CONVERT(entry USING latin1) = ‘M ‘

*I am not sure whether this problem occurs in MySQL 5.0+ as well - I think it does, since the MySQL developers have obviously seen no reason to change things.

Get free blog up and running in minutes with Blogsome
Theme designed by Janis Joseph