OverviewCairo for Symbian OS is based on Cairo version 1.8.6 with new surface backend added to allow Cairo rendering to a Symbian OS window (RWindow).
FreeType font backend and Fontconfig support have also been integrated. Pango with basic shaper engine (basic-fc module) has been ported too
... [More]
, so it is now possible to draw text using Pango instead of using Cairo "toy" text API.
Libraries used in this project i.e. expat, libpng, pixman, freetype, fontconfig and cairo are now compiled as DLLs for WINSCW, GCCE and ARMv5 build. Everything seems to work fine on both emulator and target device, but there are known isses (see this for more details).
Here are some more screenshots of S60 Cairo demo application. Please read this before installing pre-built hellocairo SIS installer.
Code ExamplesAn example how Cairo can be used from a Symbian OS application would be as follow:
// CMyAppView derives from CCoeControl
//
void CMyAppView::ConstrucL(const TRect& aRect)
{
CreateWindowL();
SetRect(aRect);
ActivateL();
iSurface = cairo_symbian_surface_create(&Window());
iContext = cairo_create(iSurface);
}// implement CCoeControl::Draw method
//
void CMyAppView::Draw(const TRect&) const
{
// start drawing using Cairo here
// please note that mixing Cairo and native rendering i.e. using CWindowGc API
// is not supported and will produce undefined result
...
cairo_t* cr = Context(); // shortcut to iContext
cairo_set_source_rgb(cr, 1, 1, 1);
cairo_paint(cr);
...
}// cleanup
//
CMyAppView::~CMyAppView()
{
...
cairo_destroy(iContext);
cairo_surface_destroy(iSurface);
}It is also possible to use Cairo for rendering into a Symbian OS pixmap (CFbsBitmap), which allows mixing between native and Cairo rendering. To do that, the existing functionality of Cairo Image Surface can be used in the following way,
...
CFbsBitmap b;
b.Create(size, displayMode);
b.LockHeap();
// cairo_format func is used to map TDisplayMode to cairo_format_t e.g.
// EColor16MU -> CAIRO_FORMAT_RGB24
// EColor16MA -> CAIRO_FORMAT_ARGB32
//
cairo_surface_t* surface = cairo_image_surface_create_for_data((unsigned char*)b.DataAddress(),
cairo_format(displayMode),
size.iWidth,
size.iHeight,
b.DataStride());
cairo_t* cr = cairo_create(surface);
draw(cr);
cairo_destroy(cr);
cairo_surface_destroy(surface);
b.UnlockHeap();
...Here's a complete code example that was used to produce rotated text shown above,
...
/* create font using Fontconfig and Cairo FT backend */
FcInit();
FcPattern *pattern = FcPatternCreate ();
FcPatternAddString (pattern, FC_FAMILY, (const FcChar8 *)"Sans");
FcPatternAddInteger (pattern, FC_SLANT, FC_SLANT_ROMAN);
FcPatternAddInteger (pattern, FC_WEIGHT, FC_WEIGHT_NORMAL);
FcResult result;
FcPattern *match = FcFontMatch (NULL, pattern, &result);
cairo_font_face_t* face = cairo_ft_font_face_create_for_pattern (match);
cairo_set_font_face (cr, face);
cairo_set_font_size (cr, 40.0);
/* draw rotated text */
for (int i=0; iScreenDevice();
const TSize sz = screen->SizeInPixels();
const TDisplayMode dm = EColor16MU;
CFbsBitmap b;
b.Create(sz, dm);
screen->CopyScreenToBitmap(&b);
b.LockHeap();
cairo_surface_t* s = cairo_image_surface_create_for_data((unsigned char*)b.DataAddress(),
CAIRO_FORMAT_RGB24,
sz.iWidth,
sz.iHeight,
b.DataStride());
cairo_surface_write_to_png(s, "c:\\data\\text.png");
cairo_surface_flush(s);
cairo_surface_destroy(s);
b.UnlockHeap();
b.Reset();
...To achieve the same result using Pango, we can use the following code,
PangoFontDescription* desc = pango_font_description_new();
pango_font_description_set_family(desc, "Sans");
pango_font_description_set_weight(desc, PANGO_WEIGHT_NORMAL);
pango_font_description_set_absolute_size(desc, 40 * PANGO_SCALE);
PangoLayout *layout = pango_cairo_create_layout(cr);
pango_layout_set_font_description(layout, desc);
pango_layout_set_text(layout, "Cairo Symbian OS", -1);
for (int i=0; iBuild InstructionsThe development is done using Nokia S60 3rd Edition SDK and Open C plugin. The build system is currently done using Symbian OS specific way (bldmake, abld). The plan is to migrate them to use standard Makefile system in the future (either using MSYS or MozillaBuild)
To build the project you need to install the following SDK and tools:
S60 3rd Edition (I'm using Feature Pack 1) Open C plugin for S60 3rd Edition (for libc, libpthread and libz) Carbide.c++ (to get Nokia/MetroWerks compiler) GCCE version 4.3.2 (to allow proper support for EPOCALLOWDLLDATA)
Pango and Cairo for Symbian OS has dependency on the following libraries, which are included in the .zip file available from Featured Downloads section:
zlib (using libz from Open C) libpng version 1.2.3.4 pixman version 0.13.2 freetype version 2.3.7 fontconfig version 2.6.0 expat version 2.0.1 pango version 1.22.2
Steps to build and test the project on S60 emulator:
Add #include to %EPOCROOT%\epoc32\include\stdapis\glib-2.0\glib.h Extract the .zip file Go to cairo-for-symbian\build directory bldmake bldfiles && abld build winscw udeb copy cairo-for-symbian\helloworld\data\romedalen.png to %EPOCROOT%\epoc32\winscw\c\data copy fonts.conf and fonts.dtd from cairo-for-symbian\fontconfig-2.6.0\projects\symbian to %EPOCROOT%\epoc32\winscw\c\data\fontconfig Launch emulator and run hellocairo application (located under Installed folder)
To build for GCCE target you need to replace GCCE that comes with SDK (version 3.4.3) with the latest version. Follow the instructions on this wikipage on how to do that. You may not have to follow all the instructions depending on your SDK environment. In my case, updating the perl scripts, d32locd.h and gcce.h is enough. The fix for missing integer division is included in this project. You may also need to modify e32def.h i.e. go to %EPOCROOT%\epoc32\include directory and modify e32def.h by replacing this line
static const char* const KSuppressPlatSecDiagnostic = KSuppressPlatSecDiagnosticMagicValue;with
static const char* const KSuppressPlatSecDiagnostic = (const char*)1;Once you've done that, build Cairo and create SIS installer for S60 phone with the following steps:
Go to cairo-for-symbian\build directory bldmake bldfiles && abld build gcce udeb Go to cairo-for-symbian\hellocairo\sis directory create_package.bat udeb
DemoIf your S60 phone is older than S60 3rd Edition Feature Pack 2, you will need to install Open C plugin into your phone first before you can run hellocairo application. Download and install Open C from here. The Open C SIS installer can be found under %S60_SDK_INSTALL_DIR%\nokia_plugin\openc\s60opencsis directory.
IssuesKnown issues:
cairo_text_path does not work and is replaced with cairo_show_text in demo application. Pango does not yet compile on ARMv5 build. Apply Jani's RVCT patch to fix that. GCCE release build somehow does not work on target device, the debug build does. Exhaustive testing has not been done, so there may be some other undiscovered bugs.
ScreenshotsSome screenshots of Cairo helloworld application running on S60 emulator (using the same code snippets found here):
arc arc negative clip clip image curve rectangle curve to dash fill and stroke fill style gradient image image pattern multi segment caps set line cap set line join text text align center text extents [Less]