Tuesday, June 24, 2008

AS3 vertical gradient fills

The examples for gradient fills are either squares, or rectangles with the gradient going from left to right:
http://livedocs.adobe.com/flex/3/langref/flash/display/Graphics.html#beginGradientFill()

So, how do you make a horizontal rectangle, with a vertical linear gradient? Everything I've tried (i.e. rotating it 90 degrees) gives me a solid colour. Here is one failure example (270 degree rotation, then translated back the height).

s.graphics.beginGradientFill(GradientType.LINEAR,
[0x666666,0x666666],[0.9,0.1],[0,255],
new Matrix(0,-1,1,0,height,0));
s.graphics.drawRect(x,y,width,height);


(I'm actually giving up and will instead make this 9 pixel high gradient (a fancy drop shadow effect) by drawing 9 lines! But, please, somebody must have some sample code they can share?)

Boost Spirit, shadowing, and a trailing newline

I've never been a fan of Boost::Spirit. It adds loads of compile time (in fact, some code failed to compile when I only had 512Mb, solely due to spirit), and the source code has shadowed variables (which causes complaints if you switch all warnings on, and therefore causes failure if you compile with -Werror).

I sent a patch in against 1.33 for the shadowed variable problems. So you can imagine my disappointment when I tried to compile against boost 1.34.1 (that comes with Ubuntu 7) and the problems were still there and required me to hack the source code again.
But that was nothing compared to how I felt when my unit tests failed to run. No compile errors, they simply failed to parse. My code was unchanged; only the boost version had changed.

I have finally tracked this down to if there is a trailing carriage-return it won't parse it. I thought the space_p parameter to parse() would take care of that, and perhaps that is the behaviour that changed between 1.33.1 and 1.34.1??

But most frustrating of all is that none of these solutions work:
'\n'
"\n"
ch_p('\n')
*ch_p('\n')
+ch_p('\n')
str_p("\n")
*str_p("\n")
+str_p("\n")

Actually I'm out of ideas!

Here is a code snippet:
GameTree = ch_p('(')[bind(&SGFMoveList::on_game_start, this, _1, fname)]
>> RootNode[bind(&SGFMoveList::on_root_node_end, this, _1,_2)]
>> *Node[bind(&SGFMoveList::on_node_end, this, _1,_2)]
>> *VariationTree
>> !ch_p(';')
>> ch_p(')')[bind(&SGFMoveList::on_game_end, this, _1)]
>> *ch_p('\n');

parse_info<const char*> info=parse(str, *GameTree , space_p);


(I've left a ch_p('\n') in there at the end, just in case it is doing some good.)

So, my solution is to check info.hit instead of info.full! hit is true if the stuff you want matched; full is the same but only gets set if the whole input string got matched. In my case a carriage-return is not getting matched, so hit is true and full is false.

That is a bit crude and may be hiding a genuine problem. So I then have a look at info.stop (which is a pointer to the part of the input string that didn't get matched) to make sure it only contains whitespace.

If anyone knows what is going on please let me know. It amazes me that no-one else has noticed this regression in Spirit, so surely it must be something I'm doing wrong?

P.S. On the next project where I needed a parser I tried Hapy (http://hapy.sourceforge.net/) instead of Spirit. It was much faster and easier to use. Its downsides are practically no-one uses it, so not much documentation, community, etc.
On most projects since then I've used Boost::tokenizer wherever possible, going out of my way to avoid writing a real parser.
The above project, where I'm using Spirit, is complex, needs a real parser, and it works, hence my reluctance to port it to Hapy, or look for something else.

Monday, June 16, 2008

Flex/Flash accessing both network and local files

Flash wants you to be safe, which means a swf you make cannot access the network (not even localhost!) and read local files. This can be a pain when you have a swf file you trust (e.g. when you wrote it yourself)! But the bigger pain is how badly Adobe document the workaround, especially if you are on linux.

First the answer. As root, make /etc/adobe/FlashPlayerTrust/. Then if your trusted swf, and its files are in /home/georgebush/killforoil/ you make a file called:
/etc/adobe/FlashPlayerTrust/killforoil.cfg
and in that cfg file you put this line:
/home/georgebush/killforoil/

George is now able to continue to screw the world without those Adobe do-gooders getting in his way.

Adobe document this (for Windows/Mac) here:
http://livedocs.adobe.com/flex/3/html/help.html?content=05B_Security_01.html

(Why am I saying the document it so badly? Because everywhere else I looked, they say using use-network=true when you make your swf file means it can never access local files.)

Once I knew that FlashPlayerTrust was the key word, I was able to find these linux instructions (which also tell you how to do per-user configurations):
http://www.abdulqabiz.com/blog/archives/flash_and_actionscript/flash_player_trust_f.php

Sunday, June 15, 2008

Gnome file associations, AIR and ZIP

I thought I'd conquered the black-box that is gnome file association configuration (see http://darrendev.blogspot.com/2008/05/gnome-whether-under-redhat-or-ubuntu-is.html)
but I'm stuck again.

Since installing Adobe AIR for linux it has associated itself with zip files. So the icon is now AIR, and the default action is to open AIR (and so when I double-click a zip file it gives me an error saying this isn't an AIR file). The only way I can open zip files is by right-clicking them now.

How do I remove that association and restore archive manager? I don't know. AIR hasn't installed anything in /usr/share/mime. And I cannot see anything in the myriad of configuration directories that live under my home directory. So, where else does gnome get its file association information from?

Please help!

Tuesday, June 3, 2008

Stopping make delete intermediate files

I wanted a makefile to compile mxml (Adobe flex, aka Flash 9) files into swf files and play them automatically. In other words I wanted to just type "make test2" and it would compile test2.mxml into test2.swf, then open test2.swf in the flashplayer.
The hardest part was that, with the automatic rules, make insisted on deleting the "intermediate" file. But in this case the intermediate file was the swf itself. There is a ".PRECIOUS" rule that appears designed for this purpose that made no difference. After much trial, error and banging my head against the keyboard until it bled, it seems setting ".SECONDARY" to blank was the solution. Here is the full makefile (saved in a file called Makefile, in the same directory as my mxml files):

MXMLC=/usr/local/src/flex3sdk/bin/mxmlc

.SECONDARY:

% : %.swf
flashplayer $<

%.swf: %.mxml
$(MXMLC) $<



This makefile is generically useful for when you want to compile and run something; especially when experimenting with lots of small individual files.

Monday, June 2, 2008

Bidirectional unicode codes and Arabic

I have been importing Arabic data into MLSN (http://dcook.org/mlsn/) (incidentally, almost all data currently comes from the AWN project). We have a csv list of synonyms, and each synonym optionally has the Arabic root in square brackets. The whole list is an SQL string, surrounded by single quotes.

When I view in SciTE it looks exactly as I'd expect: the arabic is right-to-left, the square brackets are part of the flow, and then at the apostrophe we're back to left to right. (By the way, vi appearance is the same as SciTE)
But in gedit, firefox and open office writer, when the last synonym has a square bracket it gets jumbled up.

Here is how it looks in scite:


Here is how it looks in gedit:


So, I tried adding the unicode RLE (0x202B) character before the opening square bracket and before the closing square bracket. (Incidentally, in the tab-separated file this fixed the problem in all editors.)
In SciTE no change, which is good.
In gedit et al it now has the square brackets in the flow correctly, but it has been moved to the end of the line and the following SQL clauses are now right-to-left.
Putting a unicode LRE (0x202A) before the following comma did not help! (More precisely it moved the ",'awn');" part back into the left-to-right flow, but still left the Arabic string stranded on the right; but anyway the LRE on the comma causes MySQL problems, see below.)

Is this is a bug in all of gedit, firefox and open office? Could it be a linux or gnome bug and all those applications happen to use it, while SciTE/vi do not? Or am I doing something wrong? Any advice gratefully received!

Here is how it looks in gedit with the explicit RLE codes:



MySQL and Bidirectional Codes

It seems MySQL (after doing "SET NAMES UTF8;" of course), can cope with LRE/LRE inside a quoted string, but they cannot be in the SQL string itself. E.g. on a comma.

Firefox, IE6 and Bidirectional Codes

Without the RLE codes firefox messed up showing the square brackets in both normal display and in an edit form. With the RLE codes, just before each open and each close square bracket, it shows it correctly in normal display, but still gets it wrong in the HTML form input box.
(As an aside, IE6 on Windows XP is the opposite of firefox! The main table is (very) wrong but the edit box is correct!) (And as an aside to my aside, if there is one thing Windows does well it is i18n fonts: the Arabic looks beautiful.)

phpmyadmin has a textarea that shows it correctly (with firefox). They use an explicit dir="ltr" (?!). Using that did not work for me.

So, my solution was when the edit form is being used for Arabic is to dynamically set dir to "rtl", and "ltr" the rest of the time. And (for the IE users) also set dir="rtl" on the Arabic cells, and dir="ltr" on other cells, in the main table. There is no Arabic UI currently, but when there is the dir="rtl" will be set globally via a style sheet (which is why I set the default dir="ltr" explicitly on data cells for non-Arabic languages).

See it in action by doing a search on MLSN. Here is one example: http://two.dcook.org/software/mlsn/main.php?c=06car0
(mouseover the table cells, then clicking the cell will make the edit form active; compare Arabic with the other languages.)

I am open to suggestions for alternative solutions, but I believe this is the "proper" standards, cross-browser solution.