Thanks for the quick response, Max. I'll send you the changeset tomorrow.

Cheers,
Raju

On Jan 31, 2010, at 8:02 PM, Max Carlson wrote:

> Wow - this is awesome - thanks Raju!  Replies below:
> 
> Regards,
> Max Carlson
> OpenLaszlo.org
> 
> On 1/31/10 7:42 AM, Raju Bitter wrote:
>> Henry, Max, I've done some testing to improve the functionality for rounded 
>> corners in AS3 based runtimes. Currently clipping still uses a rectangle 
>> mask independent of the cornerradius. I made some modifications to enable 
>> clipping. Here's a screenshot of the small sample app I used for testing:
>> 
>> 
>> 
>> 
>> I basically use a view with a drop shadow and rounded corners and yellow 
>> background. The 2nd item is the same view class with a red child view, 
>> centered and reduced by 12px in length and height. The 3rd item is the same 
>> yellow view with a child view containing an image that's larger then the 
>> parent view. All of the first three items use clip="true" on the yellow 
>> view. The 4th item is the same as the 3rd with clipping turned off.
>> 
>> In this process I ran into some thinks that are unclear to me in 
>> lps/kernel/swf9/LzSprite.as:
>> 
>> 1) LzSprite.clip property
>> Seems to be never set. The method LzSprite#setClip just calls applyMask and 
>> removeMask. But for clipping rounded corners, we need to access the setting 
>> for clip in the setCornerradius method. Would it be safe to store that value?
>> 
>>   public function setClip( clip:Boolean ):void {
>>         // Clip is never stored, but it's need in setCornerradius
>>         // to check if we have to apply a mask.
>>         this.clip = clip;
>>         if (clip) {
>>             applyMask();
>>         } else {
>>             removeMask();
>>         }
>>     }
> 
> Yes, it should be safe to set the property.
> 
>> 2) Drawing background and LzKernelUtils#rect
>> When drawing the background you use the method LzKernelUtils#rect. Why 
>> didn't you use the AS3 Grahipcs#rect method instead?
> 
> Mostly for consistency - it's a highly optimized method.
> 
>> 3) Scaling within applyMask()
>> The rectangle mask MovieClip in applyMask is created with a width of 1px by 
>> 1px and then scaled based on the width and height
>>                 ms.graphics.drawRect(0, 0, 1, 1);
>>                 ms.scaleX = this.lzwidth;
>>                 ms.scaleY = this.lzheight;
>> For rounded corners, that approach doesn't work, since we need to take the 
>> cornerradius value when drawing the mask using drawRoundRect(). Why did you 
>> choose to scale the mask here instead of directly setting it to lzwidth and 
>> lzheight? I used this code for creating the mask:
>>             if (this.cornerradius>  0) {
>>               ms.graphics.drawRoundRect(0, 0, this.lzwidth, this.lzheight, 
>> this.cornerradius*2);
>>             } else {
>>                 ms.graphics.drawRect(0, 0, 1, 1);
>>                 ms.scaleX = this.lzwidth;
>>                 ms.scaleY = this.lzheight;
>>             }
> 
> I suspect scaling is faster than redraws - hence the use of scaling. This 
> looks great!
> 
>> 4) Removing the mask MovieClip child from the LzSprite child list
>> Within LzSprite#removeMask you call this.removeChild(this.masksprite). I 
>> detected that after the removeChild call the LzSprite.masksprite still 
>> points to the same MovieClip object. That's a problem when I try to reapply 
>> a mask by removing the old one and creating a new (which needs to be done 
>> when setCornerradius is called and the mask has to be modified). So I 
>> explicitly set this.masksprite = null to make that work.
>>     public function removeMask():void {
>>         if (this.mask != null) {
>>             this.removeChild(this.masksprite);
>>             // With add explicitely setting the masksprite to 'null'
>>             // it will still contain the old sprite reference and
>>             // applyMask() will fail to create a new mask
>>             this.masksprite = null;
>>             this.mask = null;
>>         }
>>     }
> 
> Gret - good catch there!
> 
>> 5) Setting the cornerradius
>> When a cornerradius is set, the mask needs to be updated if clip=true. 
>> Here's the modified code I tested:
>>     var cornerradius = 0;
>>     function setCornerRadius(radius) {
>>         this.cornerradius = radius;
>>         if (this.clip) {
>>             this.removeMask();
>>             this.applyMask();
>>         }
>>         this.drawBackground();
>>     }
> 
> Awesome!
> 
>> With those changes it would be possible to clip the content of a view at the 
>> view border defined by the cornerradius. But there's a bug somewhere, the 
>> app renders correctly in SWF10 70-80% of the times, with some views 
>> sometimes not showing up when the views are clipped or the content still 
>> overlapping the mask . An interesting fact is that the drop shadow doesn't 
>> show up for the clipped elements that are visible in that case.
> 
> Hmm - I'm not sure why that would be.  This seems like a big improvement.  
> Let's get it checked in and diagnose from there.  Please send me a changeset 
> when you get a chance!
> 
>> Here's a screenshot: The 3rd item is not showing up, and in the 2nd item the 
>> red box is not clipped with the drop shadow missing on the first 2 items. I 
>> guess there's a timing problem with initialization, where the order of when 
>> a value is set varies - but you'll probably know much better.
>> 
>> 
>> 
>> 
>> 
>> 
>> With DHTML there are some other problems, mainly missing browser support for 
>> clipping based on corner radius settings. I added a comment 
>> http://jira.openlaszlo.org/jira/browse/LPP-8508 with detailed info. I 
>> attached a diff for LzSprite.as and a zip file with the example app, if you 
>> want to test.
> 
> Grr - yeah, there are lots of niggling issues there.  I don't think there's 
> much we can do about them, short of filing bugs with the browser 
> manufacturers!
> 
> -Max


Reply via email to