Thursday, June 19, 2008

Getting the ZLib dylib to link in XCode

With the link errors dropping into the 50s the home straight of something that links, though not close, seems possible. My latest teaser was some problems linking Zlib. The Cello sources include Zlib but as it exists as standard under OSX there seemed little point in compiling it into the application - also I dimly remember that there was some issue with it compiling - not that large but using the built in zlib seemed the easiest option.

Working through the link errors I came to some errors from ZLib. Adding the library libz.dylib is just a matter of dragging it in - but the link errors were not resolved. Using Google I found someone with exactly the same problem on Apple's XCode list mailing list - with a reply from Chris Espinosa but infuriatingly my guess was that the final correspondence between them happened off-list.

I eventually figured out the solution - XCode does not set the file type correctly. Just select the dylib, choose Get Info, and set the file-type.

Tuesday, June 17, 2008

Implementing MFC CTime using CFDate

In the early stages of Cello I stubbed out the MFC CTime class with little more than a constructor in order to get it to compile. Working my way through the link errors this is something that I needed to flesh out.

My basic plan with implementing these MFC classes is to keep the API but to build them on top of Core Foundation objects. Core Foundation can quite ubiquitously be expressed as NS (Objective C) objects (they are toll-free bridged) which will pay dividends when I start working in cocoa for the UI. Also, and importantly, it is all done, it works and just requires hooking up.

I implemented the CTime class as a wrapper for a CFDateRef managed by a boost intrusive_pointer. Give or take a thin wipe of code and a modest set of Unit Tests that was it.

Sunday, June 15, 2008

Implementing SetFileTime and GetFileTime under OSX

Working through the link errors makes for some catching up on some things that I sketched out and did not complete. I have been looking at the file handling class, file streams and writing unit tests to make sure that the they are working properly as I flesh them out.

I have backed Cello file handling class more or less straight onto STL file streams. In this class there are a couple of methods SetFileTime, and GetFileTime. In the MFC version these are more-or-less straight wraps of the API calls SetFileTime, and GetFileTime:
 BOOL WINAPI SetFileTime(
__in HANDLE hFile,
__in_opt const FILETIME *lpCreationTime,
__in_opt const FILETIME *lpLastAccessTime,
__in_opt const FILETIME *lpLastWriteTime
);

Under OSX I have implemented them in terms of FSGetCatalogInfo and FSSetCatalogInfo. So, for example, the blood and guts of the SetFileTime method boils out like this:
 const char *path = (LPCSTR)m_dwsName;
FSRef fsRef;
Boolean isDirectory;
FSCatalogInfo fsCatalogInfo;

OSStatus err = FSPathMakeRef(reinterpret_cast(path), &fsRef, &isDirectory);
::ThrowIfOSErr(err);
err = FSGetCatalogInfo(&fsRef, kFSCatInfoAllDates, &fsCatalogInfo, NULL, NULL, NULL);
::ThrowIfOSErr(err);

fsCatalogInfo.createDate = *lpCreationTime;
fsCatalogInfo.contentModDate = *lpLastWriteTime;
fsCatalogInfo.accessDate = *lpLastWriteTime;

err = FSSetCatalogInfo(&fsRef, kFSCatInfoAllDates, &fsCatalogInfo);
::ThrowIfOSErr(err);
In my first cut I implemented FILETIME as a CFDate - however looking at FILETIME when writing the test cases I changed this to UTCDateTime which is actually practically the same.

The only wrinkle I have found is that the FSGetCatalogInfo ignore the fractional part in the UTCDateTime - which is something that tripped me in the Unit Tests

Tuesday, June 10, 2008

CString and Unit Tests

Right at the head of the link errors was the CString class and most of it's methods. Early on in the port I copied the class declaration from MFC, commented out almost all of the methods and then uncommented the ones that as I got compile errors. It is surprising just how few of the class methods are used. At the time I knew that I wanted to implement it as a CFString so I added constructors and accessors so that I could freely convert from CFString.

Implementing the CString methods was fairly straightforward - so much so that I paused before writing any UnitTests, not wanting to waste time.


I retire some hours later with renewed belief in writing unit tests. Many of the tests worked straight off the bat - but I found serious problems in my implementation of CString::Format that would have bitten me later and would have taken longer to fix at a later date. Also using the accesors to get the underlying CFString it has been possible to check that the owner counts of the CFString are being handled correctly - I am using boost::intrusive_pointer for the actual management - but the copy constructor and assignment operations should share the underlying pointers. Unit test identified some problems here.

There is an interesting post about unit testing by Will Shipley (Delicious Monster). As well as some good info about unit testing by Chris Hanson (where I found the link to the Will Shipely post).

Monday, June 9, 2008

Link errors - Waxing the board

If XCode is to be believed I have 460 files compiling including the key file that is responsible for opening and reading the the Cello document. The next step is to wrap the "open" call in minimal snippet of cocoa and some make-shift UI. Pictured bellow is the Nib for the full FileTest UI.

The idea from here is then to surf through the link errors and, for a while, to let them drive the development. The biggest problem I can see here is that the dead-code stripping of gcc is not so good and my previous experience of the linker is that it will fail with link errors for code that is referenced but never executed.

After this my development plan is simple.
  • Once Cello links I can then work through a set of sample files testing the read.
  • When the read appears to work I can look at the file generation code and work through that.
  • When the file generation works I will work on the saving of the files. At this point I will pick up the pieces of the structured document and file compression that I have postponed.
The idea behind this approach is to get the core functionality demonstrably working and then to attack the UI.

Tuesday, June 3, 2008

QuickTime - converting Audio Formats

As I near the end of working through the output generation files I have come across the the issue of audio content. The Cello output file has sound embedded in it either as ADPCM or MP3. As Cello is a port from windows it has code that will covert from WAV (ubiquitous on Windows) to ADPCM. There is a converter class in Cello that backs onto some MFC APIs that takes care of this.

I have not done any work with sound but I figured that QuickTime might have the solution - digging around in the apple web-site in the Cocoa QuickTime sample code I found ExtractMovieAudioToAIFF that will extract a sound a movie and save it as an AFF file. QuickTime has a looser idea of what is a movie than you might think - a WAV file, for example, is considered to be a movie. The sample code as it stands will convert, for example, a WAV file to a AIFF file. It looks like I could use this code as a base or reference for converting between sound types.

I plan to postpone an work of converting sound files and will instead compile out the existing support for WAV files. I will do this as I can continue and get Cello working supporting just MP3 files. My priority is to get something working - and supporting a single audio format seems like a splendid start.

Monday, June 2, 2008

Cubics & Quadratics - Approximation results

I spent a few hours going through the Font Forge files to get a grip on how much work it would be to use it in Cello. My suspicion is that the code in Font Forge will produce better results in converting Cubics to Quadratics for fonts, simply because Fount Forge is dedicated to this kind of work and George Williams (the author) has obviously put a lot of work and consideration into the approximation - which specifically looks for various things like points of inflection when breaking the curve, and detecting Cubics that have been converted from Quadratics - something which happens with fonts.

Looking through the Font Forge code it does seem possible to map CGPaths onto the Splines and SplineSets - but it will be a bit of a fiddle to get it all working. On he other hand getting the existing Cello classes to work with CGPaths is actually quite straight forward. These classes are all written in C++ and the conversion is fairly trivial.

There is a huge amount to do so I am going with the path of least resistance. As the project progresses I can always open the Font Forge option again. It is something I would like to revisit as there is a huge amount of interesting stuff dedicated to the manipulation of splines in Font Forge.

I would personally recommend checking out the Font Forge FAQ for some great answers to questions. I particularly liked Why isn't Font Forge written in C++ - George Williams has written a great piece of software, is giving it away lock, stock and build instructions to whoever wants it for whatever purpose - it is there enjoy it.

To test the conversion of Cubics into Quadratics I took the Apple PathDemo sample code, that is in the installed with xcode in the developer folder, and made some changes. This sample code will, amongst other things, draw random paths - so the changes are quite small. I also added some code that will draw the on-curve points so that I can get an idea of the complexity of the new paths. Probably the biggest thing is Cello has it's own definitions points, lines, splines etc - and you need to satisfy the a reasonable spread of dependencies before you can use the magic ShapeVectorApproximator class.

Here are a couple of screen-shots from the test program. The grey thick line is the Cubic and the thin green one is the Quadratic.
The Quadratic on curve points are drawn in blue and the Cubic in red - so you can eaisly see that there are quite a few more cubic segments in the approximation.

If you look carefully in the image below you can see areas where the approximation breaks down and the green line strays outside of the grey - it should be in the exact centre.