Difference between revisions of "User:Ismael"
(updated the date of last change) |
(Fix spelling errors.) |
||
(8 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
− | == | + | == Developer infos == |
− | Name: Ismael | + | Name: Ismael Merzaq |
IRC Nickname: Ismael_ | IRC Nickname: Ismael_ | ||
Line 10: | Line 10: | ||
I have implemented key accelerators in native menus (like Cmd+N for new document instead of ctrl+N in the X11 version). This was my first contribution to native port and also to OOo. | I have implemented key accelerators in native menus (like Cmd+N for new document instead of ctrl+N in the X11 version). This was my first contribution to native port and also to OOo. | ||
− | I | + | I also worked on graphics for the native port: U have corrected a bug on image mask to have correct images in the menu, I implemented functions in AquaSalGraphic too (drawAlphaImage() for example). |
+ | After graphic functions, U worked on improving native windows and dialogs, and implementing missing functions of salframe.cxx (in vcl/aqua/source/window). | ||
+ | |||
+ | I'm also continuing the implementation of native controls for the Google Summer of Code 2007. For more informations, see: | ||
+ | * [[Mac OS X Porting - Native Controls]] | ||
+ | * [[MacOSX: Complete User Interface respecting Aqua Human Interface Guidelines]] | ||
+ | * My [http://lebasket.free.fr/blog/ blog] for regular news | ||
== Introduction == | == Introduction == | ||
Line 23: | Line 29: | ||
*about images (CGImage): [http://developer.apple.com/documentation/GraphicsImaging/Reference/CGImage/index.html] | *about images (CGImage): [http://developer.apple.com/documentation/GraphicsImaging/Reference/CGImage/index.html] | ||
*about graphic contexts (CGContexts): [http://developer.apple.com/documentation/GraphicsImaging/Reference/CGContext/index.html] | *about graphic contexts (CGContexts): [http://developer.apple.com/documentation/GraphicsImaging/Reference/CGContext/index.html] | ||
+ | |||
+ | == Native windows == | ||
+ | |||
+ | see [[Mac_OS_X_Porting_salframe]] | ||
== Image masks == | == Image masks == | ||
Line 28: | Line 38: | ||
=== Short intro === | === Short intro === | ||
− | As | + | As I explained it on my blog, I have continued the work Pavel Janick did on image masks. At the beginning, my work was to correct a bug concerning images in menus. I firstly thought I would have to concentrate on AquaSalMenu::SetItemImage but the problem wasn't on this function. So my work mainly concerned AquaSalBitmap::CreateMask and AquaSalBitmap::CreateWithMask functions (both located in vcl/aqua/source/gdi/salbmp.cxx). The problem came from the CreateMask function which didn't work as expected. Indeed, it created a mask with random values and so images in the menus had some pixels transparent and some others not, making the image not looking as it should. |
[[Image:AquaImageMenuBug.png]] | [[Image:AquaImageMenuBug.png]] | ||
Line 40: | Line 50: | ||
=== The possible causes of the bug === | === The possible causes of the bug === | ||
− | So the problem may come from the RawMemorySharedArray, it may also come from the creation of the CGDataProvider from it, or from the creation of the imagemask from the cgdataprovider. What is sure is that the problem comes from the CreateMask function in salbmp.cxx, but | + | So the problem may come from the RawMemorySharedArray, it may also come from the creation of the CGDataProvider from it, or from the creation of the imagemask from the cgdataprovider. What is sure is that the problem comes from the CreateMask function in salbmp.cxx, but I haven't been able to fix it. So I decided to do it by another way. |
− | === So, how did | + | === So, how did I do? === |
Instead of creating an image mask from the alpha of the original image, i created a CGImage from the alpha mask (passed as argument of the function as an AquaSalBitmap&), and i masked the original image with it, using context. | Instead of creating an image mask from the alpha of the original image, i created a CGImage from the alpha mask (passed as argument of the function as an AquaSalBitmap&), and i masked the original image with it, using context. | ||
Line 187: | Line 197: | ||
</pre> | </pre> | ||
− | + | === Key accelerators definitions in OpenOffice.org for MacOS X === | |
− | |||
− | === Key accelerators | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
+ | See [[Mac OS X Porting - Keyboard Shortcuts]]. | ||
− | --[[User:Ismael|Ismael]] | + | --[[User:Ismael|Ismael]] 16:43, 19 April 2007 (CEST) |
Latest revision as of 10:08, 27 August 2013
Developer infos
Name: Ismael Merzaq
IRC Nickname: Ismael_
blog: http://lebasket.free.fr/blog
Current work
I have implemented key accelerators in native menus (like Cmd+N for new document instead of ctrl+N in the X11 version). This was my first contribution to native port and also to OOo. I also worked on graphics for the native port: U have corrected a bug on image mask to have correct images in the menu, I implemented functions in AquaSalGraphic too (drawAlphaImage() for example). After graphic functions, U worked on improving native windows and dialogs, and implementing missing functions of salframe.cxx (in vcl/aqua/source/window).
I'm also continuing the implementation of native controls for the Google Summer of Code 2007. For more informations, see:
- Mac OS X Porting - Native Controls
- MacOSX: Complete User Interface respecting Aqua Human Interface Guidelines
- My blog for regular news
Introduction
The purpose of this page is to be a place for documentations on my work to help people who would continue my work or use it, or simply want to understand what i do. And, moreover, writing documentation is an important part of coding.
Apple Documentation and References
Apple Carbon/Quartz reference
Native windows
Image masks
Short intro
As I explained it on my blog, I have continued the work Pavel Janick did on image masks. At the beginning, my work was to correct a bug concerning images in menus. I firstly thought I would have to concentrate on AquaSalMenu::SetItemImage but the problem wasn't on this function. So my work mainly concerned AquaSalBitmap::CreateMask and AquaSalBitmap::CreateWithMask functions (both located in vcl/aqua/source/gdi/salbmp.cxx). The problem came from the CreateMask function which didn't work as expected. Indeed, it created a mask with random values and so images in the menus had some pixels transparent and some others not, making the image not looking as it should.
In the CreateMask function, the image mask is created from a RawMemorySharedArray (defined in the basebmp namespace, see in bitmapdevice.hxx. The RawMemorySharedArray uses the boost library (typedef boost::shared_array< sal_uInt8 > RawMemorySharedArray;)). Depending on the number of bits per component (colors+alpha), pixels have different values which are added to a RawMemorySharedArray. Then a CGDataprovider is created with the data of the RawMemorySharedArray (CGDataProviderRef xDataProvider( CGDataProviderCreateWithData(NULL, aMaskBuffer.get(), nHeight * nWidth, NULL) ); where aMaskBuffer is defined as basebmp::RawMemorySharedArray aMaskBuffer( new sal_uInt8[ nWidth * nHeight ] );). And finally, the image mask is created from this CGDataProvider (xMask = CGImageMaskCreate(nWidth, nHeight, 8, 8, nWidth, xDataProvider, NULL, true );).
Image and its mask (seen in Icon Composer)
The possible causes of the bug
So the problem may come from the RawMemorySharedArray, it may also come from the creation of the CGDataProvider from it, or from the creation of the imagemask from the cgdataprovider. What is sure is that the problem comes from the CreateMask function in salbmp.cxx, but I haven't been able to fix it. So I decided to do it by another way.
So, how did I do?
Instead of creating an image mask from the alpha of the original image, i created a CGImage from the alpha mask (passed as argument of the function as an AquaSalBitmap&), and i masked the original image with it, using context.
Here's the part of code which masks the image:
CGContextSaveGState(mxGraphicContext); CGContextBeginTransparencyLayer(mxGraphicContext, NULL); CGContextClipToMask(mxGraphicContext, CGRectMake( nX, nY, nDX, nDY), xMask); CGContextDrawImage(mxGraphicContext, CGRectMake( nX, nY, nDX, nDY), xImage ); xMaskedImage=CGBitmapContextCreateImage(mxGraphicContext); CGContextEndTransparencyLayer(mxGraphicContext); CGContextRestoreGState(mxGraphicContext);
We firstly save the context. Then we call CGContextBeginTransparencyLayer(mxGraphicContext, NULL) to have transparency else the transparent regions are black. Then we use the function CGContextClipToMask(mxGraphicContext, CGRectMake( nX, nY, nDX, nDY), xMask). Here's what the AppleDoc says about it:
CGContextClipToMask Maps a mask into the specified rectangle and intersects it with the current clipping area of the graphics context. void CGContextClipToMask( CGContextRef c, CGRect rect, CGImageRef mask ); [...] mask An image or an image mask. [...] Discussion If the mask parameter is an image mask, then Quartz clips in a manner identical to the behavior seen with the function CGContextDrawImage—the mask indicates an area to be left unchanged when drawing. The source samples of the image mask determine which points of the clipping area are changed, acting as an "inverse alpha" value. If the value of a source sample in the image mask is S, then the corresponding point in the current clipping area is multiplied by an alpha value of (1–S). For example, if S is 1 then the point in the clipping area becomes transparent. If S is 0, the point in the clipping area is unchanged.
Then we draw the image on the context (which has been masked) with CGContextDrawImage(mxGraphicContext, CGRectMake( nX, nY, nDX, nDY), xImage ). And we create the CGImage from this context with xMaskedImage=CGBitmapContextCreateImage(mxGraphicContext). Finally we restore the context (CGContextRestoreGState(mxGraphicContext);)
But this is not enough. Indeed, in the function CGContextClipToMask, the mask is a CGImage not the AquaSalBitmap of the arguments (CGImageRef AquaSalBitmap::CreateWithMask( const AquaSalBitmap& rMask, sal_uInt32 nX, sal_uInt32 nY, sal_uInt32 nDX, sal_uInt32 nDY )). So we have to transform the AquaSalBitmap rMask in CGImage. This is done thanks to the CreateCroppedImage function (CGImageRef AquaSalBitmap::CreateCroppedImage( int nX, int nY, int nWidth, int nHeight);) But the AquaSalBitmap rMask can't be a const, so we have 2 possibilities: remove the const in the declaration of the function, or copy the aquasalbitmap. The first solution can't be used because salgdi.cxx and other files need to have it defined with the const mask. So i used the second solution: copying the AquaSalBitmap (rMaskNew.Create( rMask ) creates a copy of rMask).
But there was still a problem. The image mask should be inverted, i.e. the black pixels should become white and the white pixels should become black.
Without inverting the mask, the parts which should be painted are transparent and those which should be transparent are painted.
So i looked for a function to do that in the OOo API. The AquaSalGraphics class provide one but it is not yet implemented. And as its implementation is, in my opinion, difficult and need some time, i didn't implement it yet and so I inverted the image mask using contexts in the function which need it. Instead of inverting the AquaSalBitmap with the OOo API, i inverted the CGImage with the Quartz API. But this solution should stay a temporary solution and, in my opinion, should be replaced as soon as possible by the one using OOo API, mainly for the clarity of code. Here's the code which invert the image thanks to context:
rMaskNew.CreateContext(); CGContextTranslateCTM (rMaskNew.mxGraphicContext, 0, mnHeight); CGContextScaleCTM (rMaskNew.mxGraphicContext, 1.0, -1.0); CGContextSetGrayFillColor(rMaskNew.mxGraphicContext, 1.0, 1.0); CGContextFillRect(rMaskNew.mxGraphicContext, CGRectMake( nX, nY, nDX, nDY)); CGContextSetBlendMode(rMaskNew.mxGraphicContext, kCGBlendModeDifference); CGContextDrawImage(rMaskNew.mxGraphicContext, CGRectMake( nX, nY, nDX, nDY), xMask); xMask=CGBitmapContextCreateImage(rMaskNew.mxGraphicContext);
Key accelerators
Short introduction: presenting the basis
The function which interests us is
void AquaSalMenu::SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, const KeyCode& rKeyCode, const XubString& rKeyName )
- nPos is the menu item index, but nPos is 0 to n based whereas the carbon API we use for ooo macport is from 1 to n+1 e.g. for the first element nPos=0, and his carbon index will be 1
- SalMenuItem* pSalMenuItem is a pointer to the menu item we want to add key accelerator
- const KeyCode& rKeyCode is the keycode of the accelerator. We can get the keycode with rKeyCode.GetCode() and the key modifier(s) (like cmd, shift, ... for Mac OS) with rKeyCode.GetAllModifier()
- const XubString& rKeyName is not used for the MacOs port
Implementation
We will use the SetMenuItemModifiers function to chose the modifier(s) of the key accelerator like cmd, shift, alt... and we'll set the key accelerator with two different function depending of the situation: the SetMenuItemCommandKey function for visible key accelerator (like for the N of Cmd+N) and the SetMenuItemKeyGlyph function for non visible characters (like for F1, F2,... or space).
Setting the key accelerator
The difficulty is that the OOo keycodes are different of the ASCII keycodes used in Carbon. For example: A is 65 in ASCII but in OOo it's 512 (defined in Key.hdl) So we have to translate from ooo codes to ascii, but the order of the characters are not exactly the same as ASCII so we translate only by intervals. We obtain this code:
if ((ncode>=KEY_A) && (ncode<=KEY_Z)) { nresultcode=ncode-KEY_A+'A'; } else if ((ncode>=KEY_0) && (ncode<=KEY_9)) { nresultcode=ncode-KEY_0+'0'; }
We do the same thing for non visible characters but instead of using the ascii code of the given character we use its carbon value.
else if((ncode>=KEY_F1) && (ncode<=KEY_F12)) { nresultcode=kMenuF1Glyph+ncode-KEY_F1; // kMenuFnGlyph=kMenuF1Glyph+n only for n<13 then it should be processed for each case } else if((ncode>=KEY_F13) && (ncode<=KEY_F15)) { nresultcode=kMenuF13Glyph+ncode-KEY_F13; //kMenuF13Glyph=0x87 and kMenuF12Glyph=0x7A } else if(ncode==KEY_SPACE) { nresultcode=kMenuSpaceGlyph; }
Then we only have to add the accelator to the menu:
- For the non visible characters: The syntax of SetMenuItemKeyGlyph is:
OSErr SetMenuItemKeyGlyph ( MenuRef inMenu, SInt16 inItem, SInt16 inGlyph );
so we use it like this:
SetMenuItemKeyGlyph ( mrMenuRef, //is the reference to the menu nPos+1, // for the reason of using nPos+1 instead of nPos see the short intro nresultcode );
- For visible characters: The syntax of SetMenuItemCommandKey is:
OSStatus SetMenuItemCommandKey ( MenuRef inMenu, MenuItemIndex inItem, Boolean inSetVirtualKey, UInt16 inKey );
so we use it like this:
SetMenuItemCommandKey ( mrMenuRef, nPos+1, 0, nresultcode );
Key accelerators definitions in OpenOffice.org for MacOS X
See Mac OS X Porting - Keyboard Shortcuts.
--Ismael 16:43, 19 April 2007 (CEST)