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