[Libreoffice-commits] .: Branch 'feature/gtk3' - 3 commits - vcl/generic vcl/headless vcl/inc vcl/Library_vcl.mk vcl/Library_vclplug_gen.mk vcl/Library_vclplug_gtk3.mk vcl/Library_vclplug_svp.mk vcl/Module_vcl.mk vcl/README vcl/unx

Michael Meeks michael at kemper.freedesktop.org
Thu Sep 29 08:15:07 PDT 2011


 vcl/Library_vcl.mk                      |    4 
 vcl/Library_vclplug_gen.mk              |    1 
 vcl/Library_vclplug_gtk3.mk             |   15 
 vcl/Library_vclplug_svp.mk              |   20 
 vcl/Module_vcl.mk                       |    4 
 vcl/README                              |    6 
 vcl/generic/app/geninst.cxx             |  134 +++
 vcl/generic/app/gensys.cxx              |  179 ++++
 vcl/generic/fontmanager/fontmanager.cxx |   23 
 vcl/generic/fontmanager/fontsubst.cxx   |  254 ++++++
 vcl/generic/print/fontsubst.cxx         |  235 -----
 vcl/generic/print/genprnpsp.cxx         |   28 
 vcl/generic/print/pspgraphics.cxx       |    2 
 vcl/headless/svpbmp.cxx                 |  330 ++++++++
 vcl/headless/svpdummies.cxx             |  119 ++
 vcl/headless/svpelement.cxx             |  294 +++++++
 vcl/headless/svpframe.cxx               |  462 +++++++++++
 vcl/headless/svpgdi.cxx                 |  702 +++++++++++++++++
 vcl/headless/svpinst.cxx                |  542 +++++++++++++
 vcl/headless/svpprn.cxx                 |  322 +++++++
 vcl/headless/svppspgraphics.cxx         | 1302 ++++++++++++++++++++++++++++++++
 vcl/headless/svptext.cxx                |  544 +++++++++++++
 vcl/headless/svpvd.cxx                  |  112 ++
 vcl/inc/generic/geninst.h               |   88 +-
 vcl/inc/generic/gensys.h                |   64 +
 vcl/inc/headless/svpbmp.hxx             |   72 +
 vcl/inc/headless/svpdummies.hxx         |  100 ++
 vcl/inc/headless/svpelement.hxx         |   49 +
 vcl/inc/headless/svpframe.hxx           |  132 +++
 vcl/inc/headless/svpgdi.hxx             |  189 ++++
 vcl/inc/headless/svpinst.hxx            |  203 ++++
 vcl/inc/headless/svpprn.hxx             |   56 +
 vcl/inc/headless/svppspgraphics.hxx     |  189 ++++
 vcl/inc/headless/svpvd.hxx              |   62 +
 vcl/inc/unx/gtk/gtkgdi.hxx              |    2 
 vcl/inc/unx/gtk/gtkinst.hxx             |    4 
 vcl/inc/unx/gtk/gtksys.hxx              |    4 
 vcl/inc/unx/headless/svpbmp.hxx         |   72 -
 vcl/inc/unx/headless/svpdummies.hxx     |  100 --
 vcl/inc/unx/headless/svpelement.hxx     |   49 -
 vcl/inc/unx/headless/svpframe.hxx       |  132 ---
 vcl/inc/unx/headless/svpgdi.hxx         |  189 ----
 vcl/inc/unx/headless/svpinst.hxx        |  203 ----
 vcl/inc/unx/headless/svpprn.hxx         |   56 -
 vcl/inc/unx/headless/svppspgraphics.hxx |  189 ----
 vcl/inc/unx/headless/svpvd.hxx          |   62 -
 vcl/inc/unx/saldata.hxx                 |    5 
 vcl/inc/unx/salinst.h                   |   29 
 vcl/inc/unx/salsys.h                    |   54 -
 vcl/inc/unx/x11/x11sys.hxx              |    4 
 vcl/unx/generic/app/saldata.cxx         |   63 -
 vcl/unx/generic/app/salinst.cxx         |  102 --
 vcl/unx/generic/app/salsys.cxx          |  113 --
 vcl/unx/generic/gdi/salgdi3.cxx         |    4 
 vcl/unx/generic/window/salframe.cxx     |    7 
 vcl/unx/gtk/app/gtkdata.cxx             |    3 
 vcl/unx/gtk/app/gtkinst.cxx             |    8 
 vcl/unx/gtk/app/gtksys.cxx              |    2 
 vcl/unx/gtk/window/gtkframe.cxx         |   22 
 vcl/unx/headless/svpbmp.cxx             |  330 --------
 vcl/unx/headless/svpdummies.cxx         |  119 --
 vcl/unx/headless/svpelement.cxx         |  294 -------
 vcl/unx/headless/svpframe.cxx           |  462 -----------
 vcl/unx/headless/svpgdi.cxx             |  702 -----------------
 vcl/unx/headless/svpinst.cxx            |  541 -------------
 vcl/unx/headless/svpprn.cxx             |  322 -------
 vcl/unx/headless/svppspgraphics.cxx     | 1302 --------------------------------
 vcl/unx/headless/svptext.cxx            |  544 -------------
 vcl/unx/headless/svpvd.cxx              |  112 --
 69 files changed, 6549 insertions(+), 6495 deletions(-)

New commits:
commit 8cc93aaa269fe9f5c1ecedb59b54e018f0ac147e
Author: Michael Meeks <michael.meeks at suse.com>
Date:   Thu Sep 29 16:14:34 2011 +0100

    headless: move backend to top-level, and enable for all platforms

diff --git a/vcl/Library_vclplug_gtk3.mk b/vcl/Library_vclplug_gtk3.mk
index d3aa016..a88e426 100644
--- a/vcl/Library_vclplug_gtk3.mk
+++ b/vcl/Library_vclplug_gtk3.mk
@@ -116,13 +116,13 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_gtk3,\
     vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk \
     vcl/unx/gtk3/window/gtk3gtkframe \
     vcl/unx/gtk3/window/gtk3gtkobject \
-    vcl/unx/headless/svpbmp \
-    vcl/unx/headless/svpdummies \
-    vcl/unx/headless/svpelement \
-    vcl/unx/headless/svpframe \
-    vcl/unx/headless/svpprn \
-    vcl/unx/headless/svptext \
-    vcl/unx/headless/svpvd \
+    vcl/headless/svpbmp \
+    vcl/headless/svpdummies \
+    vcl/headless/svpelement \
+    vcl/headless/svpframe \
+    vcl/headless/svpprn \
+    vcl/headless/svptext \
+    vcl/headless/svpvd \
 ))
 
 ifeq ($(OS),LINUX)
diff --git a/vcl/Library_vclplug_svp.mk b/vcl/Library_vclplug_svp.mk
index da2a837..6ab2051 100644
--- a/vcl/Library_vclplug_svp.mk
+++ b/vcl/Library_vclplug_svp.mk
@@ -78,16 +78,16 @@ $(eval $(call gb_Library_use_externals,vclplug_svp,\
 ))
 
 $(eval $(call gb_Library_add_exception_objects,vclplug_svp,\
-    vcl/unx/headless/svpbmp \
-    vcl/unx/headless/svpdummies \
-    vcl/unx/headless/svpelement \
-    vcl/unx/headless/svpframe \
-    vcl/unx/headless/svpgdi \
-    vcl/unx/headless/svpinst \
-    vcl/unx/headless/svpprn \
-    vcl/unx/headless/svppspgraphics \
-    vcl/unx/headless/svptext \
-    vcl/unx/headless/svpvd \
+    vcl/headless/svpbmp \
+    vcl/headless/svpdummies \
+    vcl/headless/svpelement \
+    vcl/headless/svpframe \
+    vcl/headless/svpgdi \
+    vcl/headless/svpinst \
+    vcl/headless/svpprn \
+    vcl/headless/svppspgraphics \
+    vcl/headless/svptext \
+    vcl/headless/svpvd \
 ))
 
 ifeq ($(OS),LINUX)
diff --git a/vcl/Module_vcl.mk b/vcl/Module_vcl.mk
index 224a68a..9985987 100644
--- a/vcl/Module_vcl.mk
+++ b/vcl/Module_vcl.mk
@@ -31,17 +31,17 @@ $(eval $(call gb_Module_Module,vcl))
 
 $(eval $(call gb_Module_add_targets,vcl,\
     Library_vcl \
+    Library_vclplug_svp \
     StaticLibrary_vclmain \
     Package_inc \
+	Package_afmhash \
     AllLangResTarget_vcl \
 ))
 
 ifeq ($(GUIBASE),unx)
 $(eval $(call gb_Module_add_targets,vcl,\
     Library_vclplug_gen \
-    Library_vclplug_svp \
     Library_desktop_detector \
-	Package_afmhash \
 ))
 
 ifneq ($(ENABLE_GTK),)
diff --git a/vcl/README b/vcl/README
index c752457..9e9507c 100644
--- a/vcl/README
+++ b/vcl/README
@@ -1,18 +1,16 @@
 Welcome to the Visual Class Libraries (vcl) code
 
-
 source/
 	+ the main cross-platform chunk of source
-
 inc/
 	+ cross-platform abstraction headers / definition
 	vcl/
 		+ external headers
-
 generic/
 	+ shared helper code for backends,
 	  actually built into vcl
-
+headless/
+	+ a backend renderer that draws to bitmaps
 aqua/
 	+ OS/X backend
 ios/
diff --git a/vcl/headless/svpbmp.cxx b/vcl/headless/svpbmp.cxx
new file mode 100644
index 0000000..f385682
--- /dev/null
+++ b/vcl/headless/svpbmp.cxx
@@ -0,0 +1,330 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "headless/svpbmp.hxx"
+
+#include <basegfx/vector/b2ivector.hxx>
+#include <basegfx/range/b2irange.hxx>
+#include <basebmp/scanlineformats.hxx>
+#include <basebmp/color.hxx>
+
+#include <vcl/salbtype.hxx>
+#include <vcl/bitmap.hxx>
+
+using namespace basebmp;
+using namespace basegfx;
+
+SvpSalBitmap::~SvpSalBitmap()
+{
+}
+
+bool SvpSalBitmap::Create( const Size& rSize,
+                           sal_uInt16 nBitCount,
+                           const BitmapPalette& rPalette )
+{
+    sal_uInt32 nFormat = SVP_DEFAULT_BITMAP_FORMAT;
+    switch( nBitCount )
+    {
+        case 1: nFormat = Format::ONE_BIT_MSB_PAL; break;
+        case 4: nFormat = Format::FOUR_BIT_MSB_PAL; break;
+        case 8: nFormat = Format::EIGHT_BIT_PAL; break;
+#ifdef OSL_BIGENDIAN
+        case 16: nFormat = Format::SIXTEEN_BIT_MSB_TC_MASK; break;
+#else
+        case 16: nFormat = Format::SIXTEEN_BIT_LSB_TC_MASK; break;
+#endif
+        case 24: nFormat = Format::TWENTYFOUR_BIT_TC_MASK; break;
+        case 32: nFormat = Format::THIRTYTWO_BIT_TC_MASK; break;
+    }
+    B2IVector aSize( rSize.Width(), rSize.Height() );
+    if( aSize.getX() == 0 )
+        aSize.setX( 1 );
+    if( aSize.getY() == 0 )
+        aSize.setY( 1 );
+    if( nBitCount > 8 )
+        m_aBitmap = createBitmapDevice( aSize, false, nFormat );
+    else
+    {
+        // prepare palette
+        unsigned int nEntries = 1U << nBitCount;
+        std::vector<basebmp::Color>* pPalette =
+            new std::vector<basebmp::Color>( nEntries, basebmp::Color(COL_WHITE) );
+        unsigned int nColors = rPalette.GetEntryCount();
+        for( unsigned int i = 0; i < nColors; i++ )
+        {
+            const BitmapColor& rCol = rPalette[i];
+            (*pPalette)[i] = basebmp::Color( rCol.GetRed(), rCol.GetGreen(), rCol.GetBlue() );
+        }
+        m_aBitmap = createBitmapDevice( aSize, false, nFormat,
+                                        basebmp::RawMemorySharedArray(),
+                                        basebmp::PaletteMemorySharedVector( pPalette )
+                                        );
+    }
+    return true;
+}
+
+bool SvpSalBitmap::Create( const SalBitmap& rSalBmp )
+{
+    const SvpSalBitmap& rSrc = static_cast<const SvpSalBitmap&>(rSalBmp);
+    const BitmapDeviceSharedPtr& rSrcBmp = rSrc.getBitmap();
+    if( rSrcBmp.get() )
+    {
+        B2IVector aSize = rSrcBmp->getSize();
+        m_aBitmap = cloneBitmapDevice( aSize, rSrcBmp );
+        B2IRange aRect( 0, 0, aSize.getX(), aSize.getY() );
+        m_aBitmap->drawBitmap( rSrcBmp, aRect, aRect, DrawMode_PAINT );
+    }
+    else
+        m_aBitmap.reset();
+
+    return true;
+}
+
+bool SvpSalBitmap::Create( const SalBitmap& /*rSalBmp*/,
+                           SalGraphics* /*pGraphics*/ )
+{
+    return false;
+}
+
+bool SvpSalBitmap::Create( const SalBitmap& /*rSalBmp*/,
+                           sal_uInt16 /*nNewBitCount*/ )
+{
+    return false;
+}
+
+bool SvpSalBitmap::Create( const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmapCanvas > /*xBitmapCanvas*/, Size& /*rSize*/, bool /*bMask*/ )
+{
+    return false;
+}
+
+void SvpSalBitmap::Destroy()
+{
+    m_aBitmap.reset();
+}
+
+Size SvpSalBitmap::GetSize() const
+{
+    Size aSize;
+    if( m_aBitmap.get() )
+    {
+        B2IVector aVec( m_aBitmap->getSize() );
+        aSize = Size( aVec.getX(), aVec.getY() );
+    }
+
+    return aSize;
+}
+
+sal_uInt16 SvpSalBitmap::GetBitCount() const
+{
+    sal_uInt16 nDepth = 0;
+    if( m_aBitmap.get() )
+        nDepth = getBitCountFromScanlineFormat( m_aBitmap->getScanlineFormat() );
+    return nDepth;
+}
+
+BitmapBuffer* SvpSalBitmap::AcquireBuffer( bool )
+{
+    BitmapBuffer* pBuf = NULL;
+    if( m_aBitmap.get() )
+    {
+        pBuf = new BitmapBuffer();
+        sal_uInt16 nBitCount = 1;
+        switch( m_aBitmap->getScanlineFormat() )
+        {
+            case Format::ONE_BIT_MSB_GREY:
+            case Format::ONE_BIT_MSB_PAL:
+                nBitCount = 1;
+                pBuf->mnFormat = BMP_FORMAT_1BIT_MSB_PAL;
+                break;
+            case Format::ONE_BIT_LSB_GREY:
+            case Format::ONE_BIT_LSB_PAL:
+                nBitCount = 1;
+                pBuf->mnFormat = BMP_FORMAT_1BIT_LSB_PAL;
+                break;
+            case Format::FOUR_BIT_MSB_GREY:
+            case Format::FOUR_BIT_MSB_PAL:
+                nBitCount = 4;
+                pBuf->mnFormat = BMP_FORMAT_4BIT_MSN_PAL;
+                break;
+            case Format::FOUR_BIT_LSB_GREY:
+            case Format::FOUR_BIT_LSB_PAL:
+                nBitCount = 4;
+                pBuf->mnFormat = BMP_FORMAT_4BIT_LSN_PAL;
+                break;
+            case Format::EIGHT_BIT_PAL:
+                nBitCount = 8;
+                pBuf->mnFormat = BMP_FORMAT_8BIT_PAL;
+                break;
+            case Format::EIGHT_BIT_GREY:
+                nBitCount = 8;
+                pBuf->mnFormat = BMP_FORMAT_8BIT_PAL;
+                break;
+            case Format::SIXTEEN_BIT_LSB_TC_MASK:
+                nBitCount = 16;
+                pBuf->mnFormat = BMP_FORMAT_16BIT_TC_LSB_MASK;
+                pBuf->maColorMask = ColorMask( 0xf800, 0x07e0, 0x001f );
+                break;
+            case Format::SIXTEEN_BIT_MSB_TC_MASK:
+                nBitCount = 16;
+                pBuf->mnFormat = BMP_FORMAT_16BIT_TC_MSB_MASK;
+                pBuf->maColorMask = ColorMask( 0xf800, 0x07e0, 0x001f );
+                break;
+            case Format::TWENTYFOUR_BIT_TC_MASK:
+                nBitCount = 24;
+                pBuf->mnFormat = BMP_FORMAT_24BIT_TC_BGR;
+                break;
+            case Format::THIRTYTWO_BIT_TC_MASK:
+                nBitCount = 32;
+                pBuf->mnFormat = BMP_FORMAT_32BIT_TC_MASK;
+#ifdef OSL_BIGENDIAN
+                pBuf->maColorMask = ColorMask( 0x0000ff, 0x00ff00, 0xff0000 );
+#else
+                pBuf->maColorMask = ColorMask( 0xff0000, 0x00ff00, 0x0000ff );
+#endif
+                break;
+
+            default:
+                // this is an error case !!!!!
+                nBitCount = 1;
+                pBuf->mnFormat = BMP_FORMAT_1BIT_MSB_PAL;
+                break;
+        }
+        if( m_aBitmap->isTopDown() )
+            pBuf->mnFormat |= BMP_FORMAT_TOP_DOWN;
+
+        B2IVector aSize = m_aBitmap->getSize();
+        pBuf->mnWidth           = aSize.getX();
+        pBuf->mnHeight          = aSize.getY();
+        pBuf->mnScanlineSize    = m_aBitmap->getScanlineStride();
+        pBuf->mnBitCount        = nBitCount;
+        pBuf->mpBits            = (sal_uInt8*)m_aBitmap->getBuffer().get();
+        if( nBitCount <= 8 )
+        {
+            if( m_aBitmap->getScanlineFormat() == Format::EIGHT_BIT_GREY ||
+                m_aBitmap->getScanlineFormat() == Format::FOUR_BIT_LSB_GREY ||
+                m_aBitmap->getScanlineFormat() == Format::FOUR_BIT_MSB_GREY ||
+                m_aBitmap->getScanlineFormat() == Format::ONE_BIT_LSB_GREY ||
+                m_aBitmap->getScanlineFormat() == Format::ONE_BIT_MSB_GREY
+                )
+                pBuf->maPalette = Bitmap::GetGreyPalette( 1U << nBitCount );
+            else
+            {
+                basebmp::PaletteMemorySharedVector aPalette = m_aBitmap->getPalette();
+                if( aPalette.get() )
+                {
+                    unsigned int nColors = aPalette->size();
+                    if( nColors > 0 )
+                    {
+                        pBuf->maPalette.SetEntryCount( nColors );
+                        for( unsigned int i = 0; i < nColors; i++ )
+                        {
+                            const basebmp::Color& rCol = (*aPalette)[i];
+                            pBuf->maPalette[i] = BitmapColor( rCol.getRed(), rCol.getGreen(), rCol.getBlue() );
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    return pBuf;
+}
+
+void SvpSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, bool bReadOnly )
+{
+    if( !bReadOnly && pBuffer->maPalette.GetEntryCount() )
+    {
+        // palette might have changed, clone device (but recycle
+        // memory)
+        sal_uInt16 nBitCount = 0;
+        switch( m_aBitmap->getScanlineFormat() )
+        {
+            case Format::ONE_BIT_MSB_GREY:
+                // FALLTHROUGH intended
+            case Format::ONE_BIT_MSB_PAL:
+                // FALLTHROUGH intended
+            case Format::ONE_BIT_LSB_GREY:
+                // FALLTHROUGH intended
+            case Format::ONE_BIT_LSB_PAL:
+                nBitCount = 1;
+                break;
+
+            case Format::FOUR_BIT_MSB_GREY:
+                // FALLTHROUGH intended
+            case Format::FOUR_BIT_MSB_PAL:
+                // FALLTHROUGH intended
+            case Format::FOUR_BIT_LSB_GREY:
+                // FALLTHROUGH intended
+            case Format::FOUR_BIT_LSB_PAL:
+                nBitCount = 4;
+                break;
+
+            case Format::EIGHT_BIT_PAL:
+                // FALLTHROUGH intended
+            case Format::EIGHT_BIT_GREY:
+                nBitCount = 8;
+                break;
+
+            default:
+                break;
+        }
+
+        if( nBitCount )
+        {
+            sal_uInt32 nEntries = 1U << nBitCount;
+
+            boost::shared_ptr< std::vector<basebmp::Color> > pPal(
+                new std::vector<basebmp::Color>( nEntries,
+                                                 basebmp::Color(COL_WHITE)));
+            const sal_uInt32 nColors = std::min(
+                (sal_uInt32)pBuffer->maPalette.GetEntryCount(),
+                nEntries);
+            for( sal_uInt32 i = 0; i < nColors; i++ )
+            {
+                const BitmapColor& rCol = pBuffer->maPalette[i];
+                (*pPal)[i] = basebmp::Color( rCol.GetRed(), rCol.GetGreen(), rCol.GetBlue() );
+            }
+
+            m_aBitmap = basebmp::createBitmapDevice( m_aBitmap->getSize(),
+                                                     m_aBitmap->isTopDown(),
+                                                     m_aBitmap->getScanlineFormat(),
+                                                     m_aBitmap->getBuffer(),
+                                                     pPal );
+        }
+    }
+
+    delete pBuffer;
+}
+
+bool SvpSalBitmap::GetSystemData( BitmapSystemData& )
+{
+    return false;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/headless/svpdummies.cxx b/vcl/headless/svpdummies.cxx
new file mode 100644
index 0000000..272f06c
--- /dev/null
+++ b/vcl/headless/svpdummies.cxx
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "headless/svpdummies.hxx"
+#include "headless/svpinst.hxx"
+#include <rtl/ustrbuf.hxx>
+
+// SalObject
+SvpSalObject::SvpSalObject()
+{
+    m_aSystemChildData.nSize        = sizeof( SystemChildData );
+    m_aSystemChildData.pDisplay     = NULL;
+    m_aSystemChildData.aWindow      = 0;
+    m_aSystemChildData.pSalFrame    = 0;
+    m_aSystemChildData.pWidget      = 0;
+    m_aSystemChildData.pVisual      = 0;
+    m_aSystemChildData.nDepth       = 0;
+    m_aSystemChildData.aColormap    = 0;
+    m_aSystemChildData.pAppContext  = NULL;
+    m_aSystemChildData.aShellWindow = 0;
+    m_aSystemChildData.pShellWidget = NULL;
+}
+
+SvpSalObject::~SvpSalObject()
+{
+}
+
+void SvpSalObject::ResetClipRegion() {}
+sal_uInt16 SvpSalObject::GetClipRegionType() { return 0; }
+void SvpSalObject::BeginSetClipRegion( sal_uLong ) {}
+void SvpSalObject::UnionClipRegion( long, long, long, long ) {}
+void SvpSalObject::EndSetClipRegion() {}
+void SvpSalObject::SetPosSize( long, long, long, long ) {}
+void SvpSalObject::Show( sal_Bool ) {}
+void SvpSalObject::Enable( sal_Bool ) {}
+void SvpSalObject::GrabFocus() {}
+void SvpSalObject::SetBackground() {}
+void SvpSalObject::SetBackground( SalColor ) {}
+const SystemEnvData* SvpSalObject::GetSystemData() const { return &m_aSystemChildData; }
+void SvpSalObject::InterceptChildWindowKeyDown( sal_Bool ) {}
+
+// SalI18NImeStatus
+SvpImeStatus::~SvpImeStatus() {}
+bool SvpImeStatus::canToggle() { return false; }
+void SvpImeStatus::toggle() {}
+
+// SalSystem
+SvpSalSystem::~SvpSalSystem() {}
+
+unsigned int SvpSalSystem::GetDisplayScreenCount()
+{
+    return 1;
+}
+
+unsigned int SvpSalSystem::GetDefaultDisplayNumber()
+{
+    return 0;
+}
+
+bool SvpSalSystem::IsMultiDisplay()
+{
+    return false;
+}
+
+Rectangle SvpSalSystem::GetDisplayScreenPosSizePixel( unsigned int nScreen )
+{
+    Rectangle aRect;
+    if( nScreen == 0 )
+        aRect = Rectangle( Point(0,0), Size(VIRTUAL_DESKTOP_WIDTH,VIRTUAL_DESKTOP_HEIGHT) );
+    return aRect;
+}
+
+Rectangle SvpSalSystem::GetDisplayWorkAreaPosSizePixel( unsigned int nScreen )
+{
+    return GetDisplayScreenPosSizePixel( nScreen );
+}
+
+rtl::OUString SvpSalSystem::GetScreenName( unsigned int nScreen )
+{
+   rtl::OUStringBuffer aBuf( 32 );
+   aBuf.appendAscii( "VirtualScreen " );
+   aBuf.append( sal_Int32(nScreen) );
+   return aBuf.makeStringAndClear();
+}
+
+int SvpSalSystem::ShowNativeMessageBox( const String&,
+                                        const String&,
+                                        int,
+                                        int )
+{
+    return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/headless/svpelement.cxx b/vcl/headless/svpelement.cxx
new file mode 100644
index 0000000..fb04472
--- /dev/null
+++ b/vcl/headless/svpelement.cxx
@@ -0,0 +1,294 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "headless/svpelement.hxx"
+
+#include <basebmp/scanlineformats.hxx>
+#include <tools/debug.hxx>
+#include <osl/diagnose.h>
+
+#if defined WITH_SVP_LISTENING
+#include <osl/thread.h>
+#include <vcl/svapp.hxx>
+#include <rtl/strbuf.hxx>
+#include <vcl/bitmap.hxx>
+#include <tools/stream.hxx>
+
+#include "headless/svpvd.hxx"
+#include "headless/svpbmp.hxx"
+#include "headless/svpframe.hxx"
+
+#include <list>
+#include <boost/unordered_map.hpp>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/ip.h>
+#include <stdio.h>
+#include <errno.h>
+
+using namespace basegfx;
+
+class SvpElementContainer
+{
+    std::list< SvpElement* >        m_aElements;
+    int                             m_nSocket;
+    oslThread                       m_aThread;
+
+    SvpElementContainer();
+    ~SvpElementContainer();
+    public:
+    void registerElement( SvpElement* pElement ) { m_aElements.push_back(pElement); }
+    void deregisterElement( SvpElement* pElement ) { m_aElements.remove(pElement); }
+
+    void run();
+    DECL_LINK(processRequest,void*);
+
+    static SvpElementContainer& get();
+};
+
+extern "C" void SAL_CALL SvpContainerThread( void* );
+
+SvpElementContainer& SvpElementContainer::get()
+{
+    static SvpElementContainer* pInstance = new SvpElementContainer();
+    return *pInstance;
+}
+
+SvpElementContainer::SvpElementContainer()
+{
+    static const char* pEnv = getenv("SVP_LISTENER_PORT");
+    int nPort = (pEnv && *pEnv) ? atoi(pEnv) : 8000;
+    m_nSocket = socket( PF_INET, SOCK_STREAM, 0 );
+    if( m_nSocket >= 0)
+    {
+        int nOn = 1;
+        if( setsockopt(m_nSocket, SOL_SOCKET, SO_REUSEADDR,
+                       (char*)&nOn, sizeof(nOn)) )
+        {
+            perror( "SvpElementContainer: changing socket options failed" );
+            close( m_nSocket );
+        }
+        else
+        {
+            struct sockaddr_in addr;
+            memset(&addr, 0, sizeof(struct sockaddr_in));
+            addr.sin_family = AF_INET;
+            addr.sin_port = htons(nPort);
+            addr.sin_addr.s_addr = INADDR_ANY;
+            if( bind(m_nSocket,(struct sockaddr*)&addr,sizeof(addr)) )
+            {
+                perror( "SvpElementContainer: bind() failed" );
+                close( m_nSocket );
+            }
+            else
+            {
+                if( listen( m_nSocket, 0 ) )
+                {
+                    perror( "SvpElementContainer: listen() failed" );
+                    close(m_nSocket);
+                }
+                else
+                {
+                    m_aThread = osl_createThread( SvpContainerThread, this );
+                }
+            }
+        }
+    }
+    else
+        perror( "SvpElementContainer: socket() failed\n" );
+}
+
+SvpElementContainer::~SvpElementContainer()
+{
+}
+
+void SAL_CALL SvpContainerThread(void* pSvpContainer)
+{
+    ((SvpElementContainer*)pSvpContainer)->run();
+}
+
+void SvpElementContainer::run()
+{
+    bool bRun = m_nSocket != 0;
+    while( bRun )
+    {
+        int nLocalSocket = accept( m_nSocket, NULL, NULL );
+        if( nLocalSocket < 0 )
+        {
+            bRun = false;
+            perror( "accept() failed" );
+        }
+        else
+        {
+            Application::PostUserEvent( LINK( this, SvpElementContainer, processRequest ), (void*)nLocalSocket );
+        }
+    }
+    if( m_nSocket )
+        close( m_nSocket );
+}
+
+static const char* matchType( SvpElement* pEle )
+{
+    if( dynamic_cast<SvpSalBitmap*>(pEle) )
+        return "Bitmap";
+    else if( dynamic_cast<SvpSalFrame*>(pEle) )
+        return "Frame";
+    else if( dynamic_cast<SvpSalVirtualDevice*>(pEle) )
+        return "VirtualDevice";
+    return typeid(*pEle).name();
+}
+
+IMPL_LINK( SvpElementContainer, processRequest, void*, pSocket )
+{
+    int nFile = (int)pSocket;
+
+    rtl::OStringBuffer aBuf( 256 ), aAnswer( 256 );
+    char c;
+    while( read( nFile, &c, 1 ) && c != '\n' )
+        aBuf.append( sal_Char(c) );
+    rtl::OString aCommand( aBuf.makeStringAndClear() );
+    if( aCommand.compareTo( "list", 4 ) == 0 )
+    {
+        boost::unordered_map< rtl::OString, std::list<SvpElement*>, rtl::OStringHash > aMap;
+        for( std::list< SvpElement* >::const_iterator it = m_aElements.begin();
+             it != m_aElements.end(); ++it )
+        {
+            std::list<SvpElement*>& rList = aMap[matchType(*it)];
+            rList.push_back( *it );
+        }
+        for( boost::unordered_map< rtl::OString, std::list<SvpElement*>, rtl::OStringHash>::const_iterator hash_it = aMap.begin();
+             hash_it != aMap.end(); ++hash_it )
+        {
+            aAnswer.append( "ElementType: " );
+            aAnswer.append( hash_it->first );
+            aAnswer.append( '\n' );
+            for( std::list<SvpElement*>::const_iterator it = hash_it->second.begin();
+                 it != hash_it->second.end(); ++it )
+            {
+                aAnswer.append( sal_Int64(reinterpret_cast<sal_uInt32>(*it)), 16 );
+                aAnswer.append( '\n' );
+            }
+        }
+    }
+    else if( aCommand.compareTo( "get", 3 ) == 0 )
+    {
+        sal_IntPtr aId = aCommand.copy( 3 ).toInt64( 16 );
+        SvpElement* pElement = reinterpret_cast<SvpElement*>(aId);
+        for( std::list< SvpElement* >::const_iterator it = m_aElements.begin();
+             it != m_aElements.end(); ++it )
+        {
+            if( *it == pElement )
+            {
+                const basebmp::BitmapDeviceSharedPtr& rDevice = pElement->getDevice();
+                if( rDevice.get() )
+                {
+                    SvpSalBitmap* pSalBitmap = new SvpSalBitmap();
+                    pSalBitmap->setBitmap( rDevice );
+                    Bitmap aBitmap( pSalBitmap );
+                    SvMemoryStream aStream( 256, 256 );
+                    aStream << aBitmap;
+                    aStream.Seek( STREAM_SEEK_TO_END );
+                    int nBytes = aStream.Tell();
+                    aStream.Seek( STREAM_SEEK_TO_BEGIN );
+                    aAnswer.append( (const sal_Char*)aStream.GetData(), nBytes );
+                }
+                break;
+            }
+        }
+    }
+    else if( aCommand.compareTo( "quit", 4 ) == 0 )
+    {
+        Application::Quit();
+        close( m_nSocket );
+        m_nSocket = 0;
+    }
+    write( nFile, aAnswer.getStr(), aAnswer.getLength() );
+    close( nFile );
+
+    return 0;
+}
+
+#endif
+
+using namespace basebmp;
+
+SvpElement::SvpElement()
+{
+    #if defined WITH_SVP_LISTENING
+    SvpElementContainer::get().registerElement( this );
+    #endif
+}
+
+SvpElement::~SvpElement()
+{
+    #if defined WITH_SVP_LISTENING
+    SvpElementContainer::get().deregisterElement( this );
+    #endif
+}
+
+sal_uInt32 SvpElement::getBitCountFromScanlineFormat( sal_Int32 nFormat )
+{
+    sal_uInt32 nBitCount = 1;
+    switch( nFormat )
+    {
+        case Format::ONE_BIT_MSB_GREY:
+        case Format::ONE_BIT_LSB_GREY:
+        case Format::ONE_BIT_MSB_PAL:
+        case Format::ONE_BIT_LSB_PAL:
+            nBitCount = 1;
+            break;
+        case Format::FOUR_BIT_MSB_GREY:
+        case Format::FOUR_BIT_LSB_GREY:
+        case Format::FOUR_BIT_MSB_PAL:
+        case Format::FOUR_BIT_LSB_PAL:
+            nBitCount = 4;
+            break;
+        case Format::EIGHT_BIT_PAL:
+        case Format::EIGHT_BIT_GREY:
+            nBitCount = 8;
+            break;
+        case Format::SIXTEEN_BIT_LSB_TC_MASK:
+        case Format::SIXTEEN_BIT_MSB_TC_MASK:
+            nBitCount = 16;
+            break;
+        case Format::TWENTYFOUR_BIT_TC_MASK:
+            nBitCount = 24;
+            break;
+        case Format::THIRTYTWO_BIT_TC_MASK:
+            nBitCount = 32;
+            break;
+        default:
+        OSL_FAIL( "unsupported basebmp format" );
+        break;
+    }
+    return nBitCount;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/headless/svpframe.cxx b/vcl/headless/svpframe.cxx
new file mode 100644
index 0000000..8ff0e5e
--- /dev/null
+++ b/vcl/headless/svpframe.cxx
@@ -0,0 +1,462 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "headless/svpframe.hxx"
+#include "headless/svpinst.hxx"
+#include "headless/svpgdi.hxx"
+
+#include <basebmp/scanlineformats.hxx>
+#include <basegfx/vector/b2ivector.hxx>
+
+using namespace basebmp;
+using namespace basegfx;
+
+SvpSalFrame* SvpSalFrame::s_pFocusFrame = NULL;
+
+SvpSalFrame::SvpSalFrame( SvpSalInstance* pInstance,
+                          SalFrame* pParent,
+                          sal_uLong nSalFrameStyle,
+                          SystemParentData* ) :
+    m_pInstance( pInstance ),
+    m_pParent( static_cast<SvpSalFrame*>(pParent) ),
+    m_nStyle( nSalFrameStyle ),
+    m_bVisible( false ),
+    m_nMinWidth( 0 ),
+    m_nMinHeight( 0 ),
+    m_nMaxWidth( 0 ),
+    m_nMaxHeight( 0 )
+{
+    m_aSystemChildData.nSize        = sizeof( SystemChildData );
+    m_aSystemChildData.pDisplay     = NULL;
+    m_aSystemChildData.aWindow      = 0;
+    m_aSystemChildData.pSalFrame    = this;
+    m_aSystemChildData.pWidget      = NULL;
+    m_aSystemChildData.pVisual      = NULL;
+    m_aSystemChildData.nDepth       = 24;
+    m_aSystemChildData.aColormap    = 0;
+    m_aSystemChildData.pAppContext  = NULL;
+    m_aSystemChildData.aShellWindow = 0;
+    m_aSystemChildData.pShellWidget = NULL;
+
+    if( m_pParent )
+        m_pParent->m_aChildren.push_back( this );
+
+    if( m_pInstance )
+        m_pInstance->registerFrame( this );
+
+    SetPosSize( 0, 0, 800, 600, SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
+}
+
+SvpSalFrame::~SvpSalFrame()
+{
+    if( m_pInstance )
+        m_pInstance->deregisterFrame( this );
+
+    std::list<SvpSalFrame*> Children = m_aChildren;
+    for( std::list<SvpSalFrame*>::iterator it = Children.begin();
+         it != Children.end(); ++it )
+         (*it)->SetParent( m_pParent );
+    if( m_pParent )
+        m_pParent->m_aChildren.remove( this );
+
+    if( s_pFocusFrame == this )
+    {
+        s_pFocusFrame = NULL;
+        // call directly here, else an event for a destroyed frame would be dispatched
+        CallCallback( SALEVENT_LOSEFOCUS, NULL );
+        // if the handler has not set a new focus frame
+        // pass focus to another frame, preferably a document style window
+        if( s_pFocusFrame == NULL )
+        {
+            const std::list< SalFrame* >& rFrames( m_pInstance->getFrames() );
+            for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
+            {
+                SvpSalFrame* pFrame = const_cast<SvpSalFrame*>(static_cast<const SvpSalFrame*>(*it));
+                if( pFrame->m_bVisible        &&
+                    pFrame->m_pParent == NULL &&
+                    (pFrame->m_nStyle & (SAL_FRAME_STYLE_MOVEABLE |
+                                         SAL_FRAME_STYLE_SIZEABLE |
+                                         SAL_FRAME_STYLE_CLOSEABLE) ) != 0
+                    )
+                {
+                    pFrame->GetFocus();
+                    break;
+                }
+            }
+        }
+    }
+}
+
+void SvpSalFrame::GetFocus()
+{
+    if( (m_nStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION | SAL_FRAME_STYLE_FLOAT)) == 0 )
+    {
+        if( s_pFocusFrame )
+            s_pFocusFrame->LoseFocus();
+        s_pFocusFrame = this;
+        m_pInstance->PostEvent( this, NULL, SALEVENT_GETFOCUS );
+    }
+}
+
+void SvpSalFrame::LoseFocus()
+{
+    if( s_pFocusFrame == this )
+    {
+        m_pInstance->PostEvent( this, NULL, SALEVENT_LOSEFOCUS );
+        s_pFocusFrame = NULL;
+    }
+}
+
+SalGraphics* SvpSalFrame::GetGraphics()
+{
+    SvpSalGraphics* pGraphics = new SvpSalGraphics();
+    pGraphics->setDevice( m_aFrame );
+    m_aGraphics.push_back( pGraphics );
+    return pGraphics;
+}
+
+void SvpSalFrame::ReleaseGraphics( SalGraphics* pGraphics )
+{
+    SvpSalGraphics* pSvpGraphics = dynamic_cast<SvpSalGraphics*>(pGraphics);
+    m_aGraphics.remove( pSvpGraphics );
+    delete pSvpGraphics;
+}
+
+sal_Bool SvpSalFrame::PostEvent( void* pData )
+{
+    m_pInstance->PostEvent( this, pData, SALEVENT_USEREVENT );
+    return sal_True;
+}
+
+void SvpSalFrame::PostPaint() const
+{
+    if( m_bVisible )
+    {
+        SalPaintEvent aPEvt(0, 0, maGeometry.nWidth, maGeometry.nHeight);
+        CallCallback( SALEVENT_PAINT, &aPEvt );
+    }
+}
+
+void SvpSalFrame::SetTitle( const XubString& )
+{
+}
+
+void SvpSalFrame::SetIcon( sal_uInt16 )
+{
+}
+
+void SvpSalFrame::SetMenu( SalMenu* )
+{
+}
+
+void SvpSalFrame::DrawMenuBar()
+{
+}
+
+void SvpSalFrame::SetExtendedFrameStyle( SalExtStyle )
+{
+}
+
+void SvpSalFrame::Show( sal_Bool bVisible, sal_Bool bNoActivate )
+{
+    if( bVisible && ! m_bVisible )
+    {
+        m_bVisible = true;
+        m_pInstance->PostEvent( this, NULL, SALEVENT_RESIZE );
+        if( ! bNoActivate )
+            GetFocus();
+    }
+    else if( ! bVisible && m_bVisible )
+    {
+        m_bVisible = false;
+        m_pInstance->PostEvent( this, NULL, SALEVENT_RESIZE );
+        LoseFocus();
+    }
+}
+
+void SvpSalFrame::Enable( sal_Bool )
+{
+}
+
+void SvpSalFrame::SetMinClientSize( long nWidth, long nHeight )
+{
+    m_nMinWidth = nWidth;
+    m_nMinHeight = nHeight;
+}
+
+void SvpSalFrame::SetMaxClientSize( long nWidth, long nHeight )
+{
+    m_nMaxWidth = nWidth;
+    m_nMaxHeight = nHeight;
+}
+
+void SvpSalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags )
+{
+    if( (nFlags & SAL_FRAME_POSSIZE_X) != 0 )
+        maGeometry.nX = nX;
+    if( (nFlags & SAL_FRAME_POSSIZE_Y) != 0 )
+        maGeometry.nY = nY;
+    if( (nFlags & SAL_FRAME_POSSIZE_WIDTH) != 0 )
+    {
+        maGeometry.nWidth = nWidth;
+        if( m_nMaxWidth > 0 && maGeometry.nWidth > (unsigned int)m_nMaxWidth )
+            maGeometry.nWidth = m_nMaxWidth;
+        if( m_nMinWidth > 0 && maGeometry.nWidth < (unsigned int)m_nMinWidth )
+            maGeometry.nWidth = m_nMinWidth;
+    }
+    if( (nFlags & SAL_FRAME_POSSIZE_HEIGHT) != 0 )
+    {
+        maGeometry.nHeight = nHeight;
+        if( m_nMaxHeight > 0 && maGeometry.nHeight > (unsigned int)m_nMaxHeight )
+            maGeometry.nHeight = m_nMaxHeight;
+        if( m_nMinHeight > 0 && maGeometry.nHeight < (unsigned int)m_nMinHeight )
+            maGeometry.nHeight = m_nMinHeight;
+    }
+    B2IVector aFrameSize( maGeometry.nWidth, maGeometry.nHeight );
+    if( ! m_aFrame.get() || m_aFrame->getSize() != aFrameSize )
+    {
+        if( aFrameSize.getX() == 0 )
+            aFrameSize.setX( 1 );
+        if( aFrameSize.getY() == 0 )
+            aFrameSize.setY( 1 );
+        m_aFrame = createBitmapDevice( aFrameSize, false, SVP_DEFAULT_BITMAP_FORMAT );
+        // update device in existing graphics
+        for( std::list< SvpSalGraphics* >::iterator it = m_aGraphics.begin();
+             it != m_aGraphics.end(); ++it )
+             (*it)->setDevice( m_aFrame );
+    }
+    if( m_bVisible )
+        m_pInstance->PostEvent( this, NULL, SALEVENT_RESIZE );
+}
+
+void SvpSalFrame::GetClientSize( long& rWidth, long& rHeight )
+{
+    if( m_bVisible )
+    {
+        rWidth = maGeometry.nWidth;
+        rHeight = maGeometry.nHeight;
+    }
+    else
+        rWidth = rHeight = 0;
+}
+
+void SvpSalFrame::GetWorkArea( Rectangle& rRect )
+{
+    rRect = Rectangle( Point( 0, 0 ),
+                       Size( VIRTUAL_DESKTOP_WIDTH, VIRTUAL_DESKTOP_HEIGHT ) );
+}
+
+SalFrame* SvpSalFrame::GetParent() const
+{
+    return m_pParent;
+}
+
+#define _FRAMESTATE_MASK_GEOMETRY \
+     (SAL_FRAMESTATE_MASK_X     | SAL_FRAMESTATE_MASK_Y |   \
+      SAL_FRAMESTATE_MASK_WIDTH | SAL_FRAMESTATE_MASK_HEIGHT)
+#define _FRAMESTATE_MASK_MAXIMIZED_GEOMETRY \
+     (SAL_FRAMESTATE_MASK_MAXIMIZED_X     | SAL_FRAMESTATE_MASK_MAXIMIZED_Y |   \
+      SAL_FRAMESTATE_MASK_MAXIMIZED_WIDTH | SAL_FRAMESTATE_MASK_MAXIMIZED_HEIGHT)
+
+void SvpSalFrame::SetWindowState( const SalFrameState *pState )
+{
+    if (pState == NULL)
+        return;
+
+    // Request for position or size change
+    if (pState->mnMask & _FRAMESTATE_MASK_GEOMETRY)
+    {
+        long nX = maGeometry.nX;
+        long nY = maGeometry.nY;
+        long nWidth = maGeometry.nWidth;
+        long nHeight = maGeometry.nHeight;
+
+        // change requested properties
+        if (pState->mnMask & SAL_FRAMESTATE_MASK_X)
+            nX = pState->mnX;
+        if (pState->mnMask & SAL_FRAMESTATE_MASK_Y)
+            nY = pState->mnY;
+        if (pState->mnMask & SAL_FRAMESTATE_MASK_WIDTH)
+            nWidth = pState->mnWidth;
+        if (pState->mnMask & SAL_FRAMESTATE_MASK_HEIGHT)
+            nHeight = pState->mnHeight;
+
+        SetPosSize( nX, nY, nWidth, nHeight,
+                    SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y |
+                    SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
+    }
+}
+
+sal_Bool SvpSalFrame::GetWindowState( SalFrameState* pState )
+{
+    pState->mnState = SAL_FRAMESTATE_NORMAL;
+    pState->mnX      = maGeometry.nX;
+    pState->mnY      = maGeometry.nY;
+    pState->mnWidth  = maGeometry.nWidth;
+    pState->mnHeight = maGeometry.nHeight;
+    pState->mnMask   = _FRAMESTATE_MASK_GEOMETRY | SAL_FRAMESTATE_MASK_STATE;
+
+    return sal_True;
+}
+
+void SvpSalFrame::ShowFullScreen( sal_Bool, sal_Int32 )
+{
+    SetPosSize( 0, 0, VIRTUAL_DESKTOP_WIDTH, VIRTUAL_DESKTOP_HEIGHT,
+                SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
+}
+
+void SvpSalFrame::StartPresentation( sal_Bool )
+{
+}
+
+void SvpSalFrame::SetAlwaysOnTop( sal_Bool )
+{
+}
+
+void SvpSalFrame::ToTop( sal_uInt16 )
+{
+    GetFocus();
+}
+
+void SvpSalFrame::SetPointer( PointerStyle )
+{
+}
+
+void SvpSalFrame::CaptureMouse( sal_Bool )
+{
+}
+
+void SvpSalFrame::SetPointerPos( long, long )
+{
+}
+
+void SvpSalFrame::Flush()
+{
+}
+
+void SvpSalFrame::Sync()
+{
+}
+
+void SvpSalFrame::SetInputContext( SalInputContext* )
+{
+}
+
+void SvpSalFrame::EndExtTextInput( sal_uInt16 )
+{
+}
+
+String SvpSalFrame::GetKeyName( sal_uInt16 )
+{
+    return String();
+}
+
+String SvpSalFrame::GetSymbolKeyName( const XubString&, sal_uInt16 )
+{
+    return String();
+}
+
+sal_Bool SvpSalFrame::MapUnicodeToKeyCode( sal_Unicode, LanguageType, KeyCode& )
+{
+    return sal_False;
+}
+
+LanguageType SvpSalFrame::GetInputLanguage()
+{
+    return LANGUAGE_DONTKNOW;
+}
+
+SalBitmap* SvpSalFrame::SnapShot()
+{
+    return NULL;
+}
+
+void SvpSalFrame::UpdateSettings( AllSettings& )
+{
+}
+
+void SvpSalFrame::Beep( SoundType )
+{
+}
+
+const SystemEnvData* SvpSalFrame::GetSystemData() const
+{
+    return &m_aSystemChildData;
+}
+
+SalFrame::SalPointerState SvpSalFrame::GetPointerState()
+{
+    SalPointerState aState;
+    aState.mnState = 0;
+    return aState;
+}
+
+SalFrame::SalIndicatorState SvpSalFrame::GetIndicatorState()
+{
+    SalIndicatorState aState;
+    aState.mnState = 0;
+    return aState;
+}
+
+void SvpSalFrame::SimulateKeyPress( sal_uInt16 /*nKeyCode*/ )
+{
+}
+
+void SvpSalFrame::SetParent( SalFrame* pNewParent )
+{
+    if( m_pParent )
+        m_pParent->m_aChildren.remove( this );
+    m_pParent = static_cast<SvpSalFrame*>(pNewParent);
+}
+
+bool SvpSalFrame::SetPluginParent( SystemParentData* )
+{
+    return true;
+}
+
+void SvpSalFrame::SetBackgroundBitmap( SalBitmap* )
+{
+}
+
+void SvpSalFrame::ResetClipRegion()
+{
+}
+
+void SvpSalFrame::BeginSetClipRegion( sal_uLong )
+{
+}
+
+void SvpSalFrame::UnionClipRegion( long, long, long, long )
+{
+}
+
+void SvpSalFrame::EndSetClipRegion()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx
new file mode 100644
index 0000000..c415774
--- /dev/null
+++ b/vcl/headless/svpgdi.cxx
@@ -0,0 +1,702 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "headless/svpgdi.hxx"
+#include "headless/svpbmp.hxx"
+
+#include <vcl/sysdata.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2irange.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basebmp/scanlineformats.hxx>
+
+#include <tools/debug.hxx>
+
+#if OSL_DEBUG_LEVEL > 2
+#include <basebmp/debug.hxx>
+#include <fstream>
+#include <rtl/strbuf.hxx>
+#include <sys/stat.h>
+#endif
+
+#include "headless/svppspgraphics.hxx"
+#include <region.h>
+
+using namespace basegfx;
+using namespace basebmp;
+
+inline void dbgOut( const BitmapDeviceSharedPtr&
+#if OSL_DEBUG_LEVEL > 2
+rDevice
+#endif
+)
+{
+    #if OSL_DEBUG_LEVEL > 2
+    static int dbgStreamNum = 0;
+    rtl::OStringBuffer aBuf( 256 );
+    aBuf.append( "debug" );
+    mkdir( aBuf.getStr(), 0777 );
+    aBuf.append( "/" );
+    aBuf.append( sal_Int64(reinterpret_cast<sal_IntPtr>(rDevice.get())), 16 );
+    mkdir( aBuf.getStr(), 0777 );
+    aBuf.append( "/bmp" );
+    aBuf.append( sal_Int32(dbgStreamNum++) );
+    std::fstream bmpstream( aBuf.getStr(), std::ios::out );
+    debugDump( rDevice, bmpstream );
+    #endif
+}
+
+// ===========================================================================
+
+bool SvpSalGraphics::drawAlphaBitmap( const SalTwoRect&, const SalBitmap& /*rSourceBitmap*/, const SalBitmap& /*rAlphaBitmap*/ )
+{
+    // TODO(P3) implement alpha blending
+    return false;
+}
+
+bool SvpSalGraphics::drawAlphaRect( long /*nX*/, long /*nY*/, long /*nWidth*/, long /*nHeight*/, sal_uInt8 /*nTransparency*/ )
+{
+    // TODO(P3) implement alpha blending
+    return false;
+}
+
+SvpSalGraphics::SvpSalGraphics() :
+    m_bUseLineColor( true ),
+    m_aLineColor( COL_BLACK ),
+    m_bUseFillColor( false ),
+    m_aFillColor( COL_WHITE ),
+    m_aTextColor( COL_BLACK ),
+    m_aDrawMode( DrawMode_PAINT ),
+    m_eTextFmt( Format::EIGHT_BIT_GREY ),
+    m_bClipSetup( false )
+{
+    for( int i = 0; i < MAX_FALLBACK; ++i )
+        m_pServerFont[i] = NULL;
+}
+
+SvpSalGraphics::~SvpSalGraphics()
+{
+}
+
+void SvpSalGraphics::setDevice( BitmapDeviceSharedPtr& rDevice )
+{
+    m_aOrigDevice = rDevice;
+    ResetClipRegion();
+
+    // determine matching bitmap format for masks
+    sal_uInt32 nDeviceFmt = m_aDevice->getScanlineFormat();
+    DBG_ASSERT( (nDeviceFmt <= (sal_uInt32)Format::MAX), "SVP::setDevice() with invalid bitmap format" );
+    switch( nDeviceFmt )
+    {
+        case Format::EIGHT_BIT_GREY:
+        case Format::SIXTEEN_BIT_LSB_TC_MASK:
+        case Format::SIXTEEN_BIT_MSB_TC_MASK:
+        case Format::TWENTYFOUR_BIT_TC_MASK:
+        case Format::THIRTYTWO_BIT_TC_MASK:
+            m_eTextFmt = Format::EIGHT_BIT_GREY;
+            break;
+        default:
+            m_eTextFmt = Format::ONE_BIT_LSB_GREY;
+            break;
+    }
+}
+
+void SvpSalGraphics::GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY )
+{
+    rDPIX = rDPIY = 96;
+}
+
+sal_uInt16 SvpSalGraphics::GetBitCount() const
+{
+    return SvpElement::getBitCountFromScanlineFormat( m_aDevice->getScanlineFormat() );
+}
+
+long SvpSalGraphics::GetGraphicsWidth() const
+{
+    if( m_aDevice.get() )
+    {
+        B2IVector aSize = m_aOrigDevice->getSize();
+        return aSize.getX();
+    }
+    return 0;
+}
+
+void SvpSalGraphics::ResetClipRegion()
+{
+    m_aDevice = m_aOrigDevice;
+    m_aClipMap.reset();
+    m_bClipSetup = true;
+    m_aClipRegion.SetNull();
+}
+
+
+// verify clip for the whole area is setup
+void SvpSalGraphics::ensureClip()
+{
+    if (m_bClipSetup)
+        return;
+
+    m_aDevice = m_aOrigDevice;
+    B2IVector aSize = m_aDevice->getSize();
+    m_aClipMap = createBitmapDevice( aSize, false, Format::ONE_BIT_MSB_GREY );
+    m_aClipMap->clear( basebmp::Color(0xFFFFFFFF) );
+
+    // fprintf( stderr, "non rect clip region set with %d rects:\n",
+    //         (int)m_aClipRegion.GetRectCount() );
+    ImplRegionInfo aInfo;
+    long nX, nY, nW, nH;
+    bool bRegionRect = m_aClipRegion.ImplGetFirstRect(aInfo, nX, nY, nW, nH );
+    while( bRegionRect )
+    {
+        if ( nW && nH )
+        {
+            B2DPolyPolygon aFull;
+            aFull.append( tools::createPolygonFromRect( B2DRectangle( nX, nY, nX+nW, nY+nH ) ) );
+            m_aClipMap->fillPolyPolygon( aFull, basebmp::Color(0), DrawMode_PAINT );
+        }
+    //    fprintf( stderr, "\t %ld,%ld %ldx%ld\n", nX, nY, nW, nH );
+        bRegionRect = m_aClipRegion.ImplGetNextRect( aInfo, nX, nY, nW, nH );
+    }
+    m_bClipSetup = true;
+}
+
+SvpSalGraphics::ClipUndoHandle::~ClipUndoHandle()
+{
+    if( m_aDevice.get() )
+        m_rGfx.m_aDevice = m_aDevice;
+}
+
+// setup a clip rectangle -only- iff we have to; if aRange
+// is entirely contained inside an existing clip frame, we
+// will avoid setting up the clip bitmap.
+SvpSalGraphics::ClipUndoHandle SvpSalGraphics::ensureClipFor( const basegfx::B2IRange &aRange )
+{
+    ClipUndoHandle aRet(this);
+
+    if (m_bClipSetup)
+        return aRet;
+
+    // fprintf( stderr, "ensureClipFor: %d, %d %dx%d\n",
+    //         aRange.getMinX(), aRange.getMinY(),
+    //         (int)aRange.getWidth(), (int)aRange.getHeight() );
+
+    // first see if aRange is purely internal to one of the clip regions
+    Rectangle aRect( Point( aRange.getMinX(), aRange.getMinY() ),
+                     Size( aRange.getWidth(), aRange.getHeight() ) );
+
+    // then see if we are overlapping with just one
+    int nHit = 0;
+    Rectangle aIterRect, aHitRect;
+    RegionHandle aHnd = m_aClipRegion.BeginEnumRects();
+    while( m_aClipRegion.GetNextEnumRect( aHnd, aIterRect ) )
+    {
+        if( aIterRect.IsOver( aRect ) )
+        {
+            aHitRect = aIterRect;
+            nHit++;
+        }
+    }
+    m_aClipRegion.EndEnumRects (aHnd);
+
+    if( nHit == 0 )
+    {
+        // degenerate case - we're all clipped ... hmm.
+        fprintf (stderr, "FIXME: denegerate case detected ...\n");
+    }
+    else if( nHit == 1 )
+    {
+        if( aIterRect.IsInside( aRect ) )
+        {
+    //        fprintf (stderr, " is inside ! avoid deeper clip ...\n");
+            return aRet;
+        }
+    //    fprintf (stderr, " operation only overlaps with a single clip zone\n" );
+        aRet.m_aDevice = m_aDevice;
+        m_aDevice = basebmp::subsetBitmapDevice( m_aOrigDevice,
+                                                 basegfx::B2IRange (aHitRect.Left(),
+                                                                    aHitRect.Top(),
+                                                                    aHitRect.Right(),
+                                                                    aHitRect.Bottom()) );
+        return aRet;
+    }
+    // else
+    //    fprintf (stderr, "URK: complex & slow clipping case\n" );
+
+    ensureClip();
+    return aRet;
+}
+
+
+// Clipping by creating unconditional mask bitmaps is horribly
+// slow so defer it, as much as possible. It is common to get
+// 3 rectangles pushed, and have to create a vast off-screen
+// mask only to destroy it shortly afterwards. That is
+// particularly galling if we render only to a small,
+// well defined rectangular area inside one of these clip
+// rectangles.
+//
+// ensureClipFor() or ensureClip() need to be called before
+// real rendering. FIXME: we should prolly push this down to
+// bitmapdevice instead.
+bool SvpSalGraphics::setClipRegion( const Region& i_rClip )
+{
+    m_aClipRegion = i_rClip;
+    if( i_rClip.IsEmpty() )
+    {
+        m_aClipMap.reset();
+        m_bClipSetup = true;
+    }
+    else if( i_rClip.GetRectCount() == 1 )
+    {
+        m_aClipMap.reset();
+        Rectangle aBoundRect( i_rClip.GetBoundRect() );
+        m_aDevice = basebmp::subsetBitmapDevice( m_aOrigDevice,
+                                                 basegfx::B2IRange(aBoundRect.Left(),aBoundRect.Top(),aBoundRect.Right(),aBoundRect.Bottom()) );
+        m_bClipSetup = true;
+    }
+    else
+        m_bClipSetup = false;
+    return true;
+}
+
+void SvpSalGraphics::SetLineColor()
+{
+    m_bUseLineColor = false;
+}
+
+void SvpSalGraphics::SetLineColor( SalColor nSalColor )
+{
+    m_bUseLineColor = true;
+    m_aLineColor = basebmp::Color( nSalColor );
+}
+
+void SvpSalGraphics::SetFillColor()
+{
+    m_bUseFillColor = false;
+}
+
+void SvpSalGraphics::SetFillColor( SalColor nSalColor )
+{
+    m_bUseFillColor = true;
+    m_aFillColor = basebmp::Color( nSalColor );
+}
+
+void SvpSalGraphics::SetXORMode( bool bSet, bool )
+{
+    m_aDrawMode = bSet ? DrawMode_XOR : DrawMode_PAINT;
+}
+
+void SvpSalGraphics::SetROPLineColor( SalROPColor nROPColor )
+{
+    m_bUseLineColor = true;
+    switch( nROPColor )
+    {
+        case SAL_ROP_0:
+            m_aLineColor = basebmp::Color( 0 );
+            break;
+        case SAL_ROP_1:
+            m_aLineColor = basebmp::Color( 0xffffff );
+            break;
+        case SAL_ROP_INVERT:
+            m_aLineColor = basebmp::Color( 0xffffff );
+            break;
+    }
+}
+
+void SvpSalGraphics::SetROPFillColor( SalROPColor nROPColor )
+{
+    m_bUseFillColor = true;
+    switch( nROPColor )
+    {
+        case SAL_ROP_0:
+            m_aFillColor = basebmp::Color( 0 );
+            break;
+        case SAL_ROP_1:
+            m_aFillColor = basebmp::Color( 0xffffff );
+            break;
+        case SAL_ROP_INVERT:
+            m_aFillColor = basebmp::Color( 0xffffff );
+            break;
+    }
+}
+
+void SvpSalGraphics::SetTextColor( SalColor nSalColor )
+{
+    m_aTextColor = basebmp::Color( nSalColor );
+}
+
+void SvpSalGraphics::drawPixel( long nX, long nY )
+{
+    if( m_bUseLineColor )
+    {
+        ensureClip();
+        m_aDevice->setPixel( B2IPoint( nX, nY ),
+                             m_aLineColor,
+                             m_aDrawMode,
+                             m_aClipMap
+                             );
+    }
+    dbgOut( m_aDevice );
+}
+
+void SvpSalGraphics::drawPixel( long nX, long nY, SalColor nSalColor )
+{
+    basebmp::Color aColor( nSalColor );
+    ensureClip();
+    m_aDevice->setPixel( B2IPoint( nX, nY ),
+                         aColor,
+                         m_aDrawMode,
+                         m_aClipMap
+                         );
+    dbgOut( m_aDevice );
+}
+
+void SvpSalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 )
+{
+    if( m_bUseLineColor )
+    {
+        ensureClip(); // FIXME: for ...
+        m_aDevice->drawLine( B2IPoint( nX1, nY1 ),
+                             B2IPoint( nX2, nY2 ),
+                             m_aLineColor,
+                             m_aDrawMode,
+                             m_aClipMap );
+    }
+    dbgOut( m_aDevice );
+}
+
+void SvpSalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight )
+{
+    if( m_bUseLineColor || m_bUseFillColor )
+    {
+        B2DPolygon aRect = tools::createPolygonFromRect( B2DRectangle( nX, nY, nX+nWidth, nY+nHeight ) );
+        ensureClip(); // FIXME: for ...
+        if( m_bUseFillColor )
+        {
+            B2DPolyPolygon aPolyPoly( aRect );
+            m_aDevice->fillPolyPolygon( aPolyPoly, m_aFillColor, m_aDrawMode, m_aClipMap );
+        }
+        if( m_bUseLineColor )
+            m_aDevice->drawPolygon( aRect, m_aLineColor, m_aDrawMode, m_aClipMap );
+    }
+    dbgOut( m_aDevice );
+}
+
+void SvpSalGraphics::drawPolyLine( sal_uLong nPoints, const SalPoint* pPtAry )
+{
+    if( m_bUseLineColor && nPoints )
+    {
+        B2DPolygon aPoly;
+        aPoly.append( B2DPoint( pPtAry->mnX, pPtAry->mnY ), nPoints );
+        for( sal_uLong i = 1; i < nPoints; i++ )
+            aPoly.setB2DPoint( i, B2DPoint( pPtAry[i].mnX, pPtAry[i].mnY ) );
+        aPoly.setClosed( false );
+        ensureClip(); // FIXME: for ...
+        m_aDevice->drawPolygon( aPoly, m_aLineColor, m_aDrawMode, m_aClipMap );
+    }
+    dbgOut( m_aDevice );
+}
+
+void SvpSalGraphics::drawPolygon( sal_uLong nPoints, const SalPoint* pPtAry )
+{
+    if( ( m_bUseLineColor || m_bUseFillColor ) && nPoints )
+    {
+        B2DPolygon aPoly;
+        aPoly.append( B2DPoint( pPtAry->mnX, pPtAry->mnY ), nPoints );
+        for( sal_uLong i = 1; i < nPoints; i++ )
+            aPoly.setB2DPoint( i, B2DPoint( pPtAry[i].mnX, pPtAry[i].mnY ) );
+        ensureClip(); // FIXME: for ...
+        if( m_bUseFillColor )
+        {
+            aPoly.setClosed( true );
+            m_aDevice->fillPolyPolygon( B2DPolyPolygon(aPoly), m_aFillColor, m_aDrawMode, m_aClipMap );
+        }
+        if( m_bUseLineColor )
+        {
+            aPoly.setClosed( false );
+            m_aDevice->drawPolygon( aPoly, m_aLineColor, m_aDrawMode, m_aClipMap );
+        }
+    }
+    dbgOut( m_aDevice );
+}
+
+void SvpSalGraphics::drawPolyPolygon( sal_uInt32        nPoly,
+                                      const sal_uInt32* pPointCounts,
+                                      PCONSTSALPOINT*   pPtAry )
+{
+    if( ( m_bUseLineColor || m_bUseFillColor ) && nPoly )
+    {
+        B2DPolyPolygon aPolyPoly;
+        for( sal_uInt32 nPolygon = 0; nPolygon < nPoly; nPolygon++ )
+        {
+            sal_uInt32 nPoints = pPointCounts[nPolygon];
+            if( nPoints )
+            {
+                PCONSTSALPOINT pPoints = pPtAry[nPolygon];
+                B2DPolygon aPoly;
+                aPoly.append( B2DPoint( pPoints->mnX, pPoints->mnY ), nPoints );
+                for( sal_uInt32 i = 1; i < nPoints; i++ )
+                    aPoly.setB2DPoint( i, B2DPoint( pPoints[i].mnX, pPoints[i].mnY ) );
+
+                aPolyPoly.append( aPoly );
+            }
+        }
+        ensureClip(); // FIXME: for ...
+        if( m_bUseFillColor )
+        {
+            aPolyPoly.setClosed( true );
+            m_aDevice->fillPolyPolygon( aPolyPoly, m_aFillColor, m_aDrawMode, m_aClipMap );
+        }
+        if( m_bUseLineColor )
+        {
+            aPolyPoly.setClosed( false );
+            nPoly = aPolyPoly.count();
+            for( sal_uInt32 i = 0; i < nPoly; i++ )
+                m_aDevice->drawPolygon( aPolyPoly.getB2DPolygon(i), m_aLineColor, m_aDrawMode, m_aClipMap );
+        }
+    }
+    dbgOut( m_aDevice );
+}
+
+bool SvpSalGraphics::drawPolyLine( const ::basegfx::B2DPolygon&, double /*fTransparency*/, const ::basegfx::B2DVector& /*rLineWidths*/, basegfx::B2DLineJoin /*eJoin*/ )
+{
+        // TODO: implement and advertise OutDevSupport_B2DDraw support
+        return false;
+}
+
+sal_Bool SvpSalGraphics::drawPolyLineBezier( sal_uLong,
+                                             const SalPoint*,
+                                             const sal_uInt8* )
+{
+    return sal_False;
+}
+
+sal_Bool SvpSalGraphics::drawPolygonBezier( sal_uLong,
+                                            const SalPoint*,
+                                            const sal_uInt8* )
+{
+    return sal_False;
+}
+
+sal_Bool SvpSalGraphics::drawPolyPolygonBezier( sal_uInt32,
+                                                const sal_uInt32*,
+                                                const SalPoint* const*,
+                                                const sal_uInt8* const* )
+{
+    return sal_False;
+}
+
+bool SvpSalGraphics::drawPolyPolygon( const basegfx::B2DPolyPolygon&, double /*fTransparency*/ )
+{
+    // TODO: maybe BaseBmp can draw B2DPolyPolygons directly
+    return false;
+}
+
+void SvpSalGraphics::copyArea( long nDestX,
+                                      long nDestY,
+                                      long nSrcX,
+                                      long nSrcY,
+                                      long nSrcWidth,
+                                      long nSrcHeight,
+                                      sal_uInt16 /*nFlags*/ )
+{
+    B2IRange aSrcRect( nSrcX, nSrcY, nSrcX+nSrcWidth, nSrcY+nSrcHeight );
+    B2IRange aDestRect( nDestX, nDestY, nDestX+nSrcWidth, nDestY+nSrcHeight );
+    // fprintf( stderr, "copyArea %ld pixels - clip region %d\n",
+    //         (long)(nSrcWidth * nSrcHeight), m_aClipMap.get() != NULL );
+    SvpSalGraphics::ClipUndoHandle aUndo = ensureClipFor( aDestRect );
+    m_aDevice->drawBitmap( m_aOrigDevice, aSrcRect, aDestRect, DrawMode_PAINT, m_aClipMap );
+    dbgOut( m_aDevice );
+}
+
+void SvpSalGraphics::copyBits( const SalTwoRect* pPosAry,
+                               SalGraphics*      pSrcGraphics )
+{
+    SvpSalGraphics* pSrc = pSrcGraphics ?
+        static_cast<SvpSalGraphics*>(pSrcGraphics) : this;
+    B2IRange aSrcRect( pPosAry->mnSrcX, pPosAry->mnSrcY,
+                       pPosAry->mnSrcX+pPosAry->mnSrcWidth,
+                       pPosAry->mnSrcY+pPosAry->mnSrcHeight );
+    B2IRange aDestRect( pPosAry->mnDestX, pPosAry->mnDestY,
+                        pPosAry->mnDestX+pPosAry->mnDestWidth,
+                        pPosAry->mnDestY+pPosAry->mnDestHeight );
+    SvpSalGraphics::ClipUndoHandle aUndo = ensureClipFor( aDestRect );
+    m_aDevice->drawBitmap( pSrc->m_aOrigDevice, aSrcRect, aDestRect, DrawMode_PAINT, m_aClipMap );
+    dbgOut( m_aDevice );
+}
+
+void SvpSalGraphics::drawBitmap( const SalTwoRect* pPosAry,
+                                        const SalBitmap& rSalBitmap )
+{
+    const SvpSalBitmap& rSrc = static_cast<const SvpSalBitmap&>(rSalBitmap);
+    B2IRange aSrcRect( pPosAry->mnSrcX, pPosAry->mnSrcY,
+                       pPosAry->mnSrcX+pPosAry->mnSrcWidth,
+                       pPosAry->mnSrcY+pPosAry->mnSrcHeight );
+    B2IRange aDestRect( pPosAry->mnDestX, pPosAry->mnDestY,
+                        pPosAry->mnDestX+pPosAry->mnDestWidth,
+                        pPosAry->mnDestY+pPosAry->mnDestHeight );
+    SvpSalGraphics::ClipUndoHandle aUndo = ensureClipFor( aDestRect );
+    m_aDevice->drawBitmap( rSrc.getBitmap(), aSrcRect, aDestRect, DrawMode_PAINT, m_aClipMap );
+    dbgOut( m_aDevice );
+}
+
+void SvpSalGraphics::drawBitmap( const SalTwoRect*,
+                                 const SalBitmap&,
+                                 SalColor )
+{
+    // SNI, as in X11 plugin
+}
+
+void SvpSalGraphics::drawBitmap( const SalTwoRect* pPosAry,
+                                 const SalBitmap& rSalBitmap,
+                                 const SalBitmap& rTransparentBitmap )
+{
+    const SvpSalBitmap& rSrc = static_cast<const SvpSalBitmap&>(rSalBitmap);
+    const SvpSalBitmap& rSrcTrans = static_cast<const SvpSalBitmap&>(rTransparentBitmap);
+    B2IRange aSrcRect( pPosAry->mnSrcX, pPosAry->mnSrcY,
+                       pPosAry->mnSrcX+pPosAry->mnSrcWidth,
+                       pPosAry->mnSrcY+pPosAry->mnSrcHeight );
+    B2IRange aDestRect( pPosAry->mnDestX, pPosAry->mnDestY,
+                        pPosAry->mnDestX+pPosAry->mnDestWidth,
+                        pPosAry->mnDestY+pPosAry->mnDestHeight );
+    SvpSalGraphics::ClipUndoHandle aUndo = ensureClipFor( aDestRect );
+    m_aDevice->drawMaskedBitmap( rSrc.getBitmap(), rSrcTrans.getBitmap(), aSrcRect, aDestRect, DrawMode_PAINT, m_aClipMap );
+    dbgOut( m_aDevice );
+}
+
+void SvpSalGraphics::drawMask( const SalTwoRect* pPosAry,
+                               const SalBitmap& rSalBitmap,
+                               SalColor nMaskColor )
+{
+    const SvpSalBitmap& rSrc = static_cast<const SvpSalBitmap&>(rSalBitmap);
+    B2IRange aSrcRect( pPosAry->mnSrcX, pPosAry->mnSrcY,
+                       pPosAry->mnSrcX+pPosAry->mnSrcWidth,
+                       pPosAry->mnSrcY+pPosAry->mnSrcHeight );
+    B2IPoint aDestPoint( pPosAry->mnDestX, pPosAry->mnDestY );
+
+    // BitmapDevice::drawMaskedColor works with 0==transparent,
+    // 255==opaque. drawMask() semantic is the other way
+    // around. Therefore, invert mask.
+    BitmapDeviceSharedPtr aCopy =
+        cloneBitmapDevice( B2IVector( pPosAry->mnSrcWidth, pPosAry->mnSrcHeight ),
+                           rSrc.getBitmap() );
+    basebmp::Color aBgColor( COL_WHITE );
+    aCopy->clear(aBgColor);
+    basebmp::Color aFgColor( COL_BLACK );
+    aCopy->drawMaskedColor( aFgColor, rSrc.getBitmap(), aSrcRect, B2IPoint() );
+
+    basebmp::Color aColor( nMaskColor );
+    B2IRange aSrcRect2( 0, 0, pPosAry->mnSrcWidth, pPosAry->mnSrcHeight );
+    const B2IRange aClipRect( aDestPoint, B2ITuple( aSrcRect.getWidth(), aSrcRect.getHeight() ) );
+    SvpSalGraphics::ClipUndoHandle aUndo = ensureClipFor( aClipRect );
+    m_aDevice->drawMaskedColor( aColor, aCopy, aSrcRect, aDestPoint, m_aClipMap );
+    dbgOut( m_aDevice );
+}
+
+SalBitmap* SvpSalGraphics::getBitmap( long nX, long nY, long nWidth, long nHeight )
+{
+    BitmapDeviceSharedPtr aCopy =
+        cloneBitmapDevice( B2IVector( nWidth, nHeight ),
+                           m_aDevice );
+    B2IRange aSrcRect( nX, nY, nX+nWidth, nY+nHeight );
+    B2IRange aDestRect( 0, 0, nWidth, nHeight );
+    SvpSalGraphics::ClipUndoHandle aUndo = ensureClipFor( aDestRect );
+    aCopy->drawBitmap( m_aOrigDevice, aSrcRect, aDestRect, DrawMode_PAINT );
+
+    SvpSalBitmap* pBitmap = new SvpSalBitmap();
+    pBitmap->setBitmap( aCopy );
+    return pBitmap;
+}
+
+SalColor SvpSalGraphics::getPixel( long nX, long nY )
+{
+    basebmp::Color aColor( m_aOrigDevice->getPixel( B2IPoint( nX, nY ) ) );
+    return aColor.toInt32();
+}
+
+void SvpSalGraphics::invert( long nX, long nY, long nWidth, long nHeight, SalInvert /*nFlags*/ )
+{
+    // FIXME: handle SAL_INVERT_50 and SAL_INVERT_TRACKFRAME
+    B2DPolygon aRect = tools::createPolygonFromRect( B2DRectangle( nX, nY, nX+nWidth, nY+nHeight ) );
+    B2DPolyPolygon aPolyPoly( aRect );
+    ensureClip(); // FIXME for ...
+    m_aDevice->fillPolyPolygon( aPolyPoly, basebmp::Color( 0xffffff ), DrawMode_XOR, m_aClipMap );
+    dbgOut( m_aDevice );
+}
+
+void SvpSalGraphics::invert( sal_uLong nPoints, const SalPoint* pPtAry, SalInvert /*nFlags*/ )
+{
+    // FIXME: handle SAL_INVERT_50 and SAL_INVERT_TRACKFRAME
+    B2DPolygon aPoly;
+    aPoly.append( B2DPoint( pPtAry->mnX, pPtAry->mnY ), nPoints );
+    for( sal_uLong i = 1; i < nPoints; i++ )
+        aPoly.setB2DPoint( i, B2DPoint( pPtAry[i].mnX, pPtAry[i].mnY ) );
+    aPoly.setClosed( true );
+    ensureClip(); // FIXME for ...
+    m_aDevice->fillPolyPolygon( B2DPolyPolygon(aPoly), basebmp::Color( 0xffffff ), DrawMode_XOR, m_aClipMap );
+    dbgOut( m_aDevice );
+}
+
+sal_Bool SvpSalGraphics::drawEPS( long, long, long, long, void*, sal_uLong )
+{
+    return sal_False;
+}
+
+SystemFontData SvpSalGraphics::GetSysFontData( int nFallbacklevel ) const
+{
+    SystemFontData aSysFontData;
+
+    if (nFallbacklevel >= MAX_FALLBACK) nFallbacklevel = MAX_FALLBACK - 1;
+    if (nFallbacklevel < 0 ) nFallbacklevel = 0;
+
+    aSysFontData.nSize = sizeof( SystemFontData );
+    aSysFontData.nFontId = 0;
+    aSysFontData.nFontFlags = 0;
+    aSysFontData.bFakeBold = false;
+    aSysFontData.bFakeItalic = false;
+    aSysFontData.bAntialias = true;
+    return aSysFontData;
+}
+
+SystemGraphicsData SvpSalGraphics::GetGraphicsData() const
+{
+    SystemGraphicsData aRes;
+    aRes.nSize = sizeof(aRes);
+    aRes.hDrawable = 0;
+    aRes.pXRenderFormat = 0;
+    return aRes;
+}
+
+bool SvpSalGraphics::supportsOperation( OutDevSupportType ) const
+{
+    return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/headless/svpinst.cxx b/vcl/headless/svpinst.cxx
new file mode 100644
index 0000000..182cf86
--- /dev/null
+++ b/vcl/headless/svpinst.cxx
@@ -0,0 +1,542 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+
+#include <sal/types.h>
+
+#include <vcl/apptypes.hxx>
+
+#include "headless/svpinst.hxx"
+#include "headless/svpframe.hxx"
+#include "headless/svpdummies.hxx"
+#include "headless/svpvd.hxx"
+#include "headless/svpbmp.hxx"
+
+#include <salframe.hxx>
+#include <svdata.hxx>
+#include <saldatabasic.hxx>
+#include <vcl/solarmutex.hxx>
+
+// FIXME: split off into a separate, standalone module to aid linking
+#ifndef GTK3_INCLUDED
+// plugin factory function
+extern "C"
+{
+    SAL_DLLPUBLIC_EXPORT SalInstance* create_SalInstance()
+    {
+        SvpSalInstance* pInstance = new SvpSalInstance();
+        SalData* pSalData = new SalData();
+        pSalData->m_pInstance = pInstance;
+        SetSalData( pSalData );
+        return pInstance;
+    }
+}
+#endif
+
+bool SvpSalInstance::isFrameAlive( const SalFrame* pFrame ) const
+{
+    for( std::list< SalFrame* >::const_iterator it = m_aFrames.begin();
+         it != m_aFrames.end(); ++it )
+    {
+        if( *it == pFrame )
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+SvpSalInstance* SvpSalInstance::s_pDefaultInstance = NULL;
+
+SvpSalInstance::SvpSalInstance() :
+    SalGenericInstance( new SalYieldMutex() )
+{
+    m_aTimeout.tv_sec       = 0;
+    m_aTimeout.tv_usec      = 0;
+    m_nTimeoutMS            = 0;
+
+    m_pTimeoutFDS[0] = m_pTimeoutFDS[1] = -1;
+    if (pipe (m_pTimeoutFDS) != -1)
+    {
+        // initialize 'wakeup' pipe.
+        int flags;
+
+        // set close-on-exec descriptor flag.
+        if ((flags = fcntl (m_pTimeoutFDS[0], F_GETFD)) != -1)
+        {
+            flags |= FD_CLOEXEC;
+            fcntl (m_pTimeoutFDS[0], F_SETFD, flags);
+        }
+        if ((flags = fcntl (m_pTimeoutFDS[1], F_GETFD)) != -1)
+        {
+            flags |= FD_CLOEXEC;
+            fcntl (m_pTimeoutFDS[1], F_SETFD, flags);
+        }
+
+        // set non-blocking I/O flag.
+        if ((flags = fcntl (m_pTimeoutFDS[0], F_GETFL)) != -1)
+        {
+            flags |= O_NONBLOCK;
+            fcntl (m_pTimeoutFDS[0], F_SETFL, flags);
+        }
+        if ((flags = fcntl (m_pTimeoutFDS[1], F_GETFL)) != -1)
+        {
+            flags |= O_NONBLOCK;
+            fcntl (m_pTimeoutFDS[1], F_SETFL, flags);
+        }
+    }
+    m_aEventGuard = osl_createMutex();
+    if( s_pDefaultInstance == NULL )
+        s_pDefaultInstance = this;
+}
+
+SvpSalInstance::~SvpSalInstance()
+{
+    if( s_pDefaultInstance == this )
+        s_pDefaultInstance = NULL;
+
+    // close 'wakeup' pipe.
+    close (m_pTimeoutFDS[0]);
+    close (m_pTimeoutFDS[1]);
+    osl_destroyMutex( m_aEventGuard );
+}
+
+void SvpSalInstance::PostEvent( const SalFrame* pFrame, void* pData, sal_uInt16 nEvent )
+{
+    if( osl_acquireMutex( m_aEventGuard ) )
+    {
+        m_aUserEvents.push_back( SalUserEvent( pFrame, pData, nEvent ) );
+        osl_releaseMutex( m_aEventGuard );
+    }
+    Wakeup();
+}
+
+void SvpSalInstance::CancelEvent( const SalFrame* pFrame, void* pData, sal_uInt16 nEvent )
+{
+    if( osl_acquireMutex( m_aEventGuard ) )
+    {
+        if( ! m_aUserEvents.empty() )
+        {
+            std::list< SalUserEvent >::iterator it = m_aUserEvents.begin();
+            do
+            {
+                if( it->m_pFrame    == pFrame   &&
+                    it->m_pData     == pData    &&
+                    it->m_nEvent    == nEvent )
+                {
+                    it = m_aUserEvents.erase( it );
+                }
+                else
+                    ++it;
+            } while( it != m_aUserEvents.end() );
+        }
+        osl_releaseMutex( m_aEventGuard );
+    }
+}
+
+void SvpSalInstance::deregisterFrame( SalFrame* pFrame )
+{
+    m_aFrames.remove( pFrame );
+
+    if( osl_acquireMutex( m_aEventGuard ) )
+    {
+        // cancel outstanding events for this frame
+        if( ! m_aUserEvents.empty() )
+        {
+            std::list< SalUserEvent >::iterator it = m_aUserEvents.begin();
+            do
+            {
+                if( it->m_pFrame    == pFrame )
+                {
+                    it = m_aUserEvents.erase( it );
+                }
+                else
+                    ++it;
+            } while( it != m_aUserEvents.end() );
+        }
+        osl_releaseMutex( m_aEventGuard );
+    }
+}
+
+void SvpSalInstance::Wakeup()
+{
+    OSL_VERIFY(write (m_pTimeoutFDS[1], "", 1) == 1);
+}
+
+// FIXME: share this with unx/generic [!] ....
+#ifndef GTK3_INCLUDED
+// -=-= timeval =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+inline int operator >= ( const timeval &t1, const timeval &t2 )
+{
+    if( t1.tv_sec == t2.tv_sec )
+        return t1.tv_usec >= t2.tv_usec;
+    return t1.tv_sec > t2.tv_sec;
+}
+inline timeval &operator += ( timeval &t1, sal_uLong t2 )
+{
+    t1.tv_sec  += t2 / 1000;
+    t1.tv_usec += t2 ? (t2 % 1000) * 1000 : 500;
+    if( t1.tv_usec > 1000000 )
+    {
+        t1.tv_sec++;
+        t1.tv_usec -= 1000000;
+    }
+    return t1;
+}
+inline int operator > ( const timeval &t1, const timeval &t2 )
+{
+    if( t1.tv_sec == t2.tv_sec )
+        return t1.tv_usec > t2.tv_usec;
+    return t1.tv_sec > t2.tv_sec;
+}
+#endif
+
+bool SvpSalInstance::CheckTimeout( bool bExecuteTimers )
+{
+    bool bRet = false;
+    if( m_aTimeout.tv_sec ) // timer is started
+    {
+        timeval aTimeOfDay;
+        gettimeofday( &aTimeOfDay, 0 );
+        if( aTimeOfDay >= m_aTimeout )
+        {
+            bRet = true;
+            if( bExecuteTimers )
+            {
+                // timed out, update timeout
+                m_aTimeout = aTimeOfDay;
+                m_aTimeout += m_nTimeoutMS;
+                // notify
+                ImplSVData* pSVData = ImplGetSVData();
+                if( pSVData->mpSalTimer )
+                    pSVData->mpSalTimer->CallCallback();
+            }
+        }
+    }
+    return bRet;
+}
+
+SalFrame* SvpSalInstance::CreateChildFrame( SystemParentData* pParent, sal_uLong nStyle )
+{
+    return new SvpSalFrame( this, NULL, nStyle, pParent );
+}
+
+SalFrame* SvpSalInstance::CreateFrame( SalFrame* pParent, sal_uLong nStyle )
+{
+    return new SvpSalFrame( this, pParent, nStyle );
+}
+
+void SvpSalInstance::DestroyFrame( SalFrame* pFrame )
+{
+    delete pFrame;
+}
+
+SalObject* SvpSalInstance::CreateObject( SalFrame*, SystemWindowData*, sal_Bool )
+{
+    return new SvpSalObject();
+}
+
+void SvpSalInstance::DestroyObject( SalObject* pObject )
+{
+    delete pObject;
+}
+
+SalVirtualDevice* SvpSalInstance::CreateVirtualDevice( SalGraphics*,
+                                                       long nDX, long nDY,
+                                                       sal_uInt16 nBitCount, const SystemGraphicsData* )
+{
+    SvpSalVirtualDevice* pNew = new SvpSalVirtualDevice( nBitCount );
+    pNew->SetSize( nDX, nDY );
+    return pNew;
+}
+
+void SvpSalInstance::DestroyVirtualDevice( SalVirtualDevice* pDevice )
+{
+    delete pDevice;
+}
+
+SalTimer* SvpSalInstance::CreateSalTimer()
+{
+    return new SvpSalTimer( this );
+}
+
+SalI18NImeStatus* SvpSalInstance::CreateI18NImeStatus()
+{
+    return new SvpImeStatus();
+}
+
+SalSystem* SvpSalInstance::CreateSalSystem()
+{
+    return new SvpSalSystem();
+}
+
+SalBitmap* SvpSalInstance::CreateSalBitmap()
+{
+    return new SvpSalBitmap();
+}
+
+osl::SolarMutex* SvpSalInstance::GetYieldMutex()
+{
+    return &m_aYieldMutex;
+}
+
+sal_uLong SvpSalInstance::ReleaseYieldMutex()
+{
+    if ( m_aYieldMutex.GetThreadId() ==
+         osl::Thread::getCurrentIdentifier() )
+    {
+        sal_uLong nCount = m_aYieldMutex.GetAcquireCount();
+        sal_uLong n = nCount;
+        while ( n )
+        {
+            m_aYieldMutex.release();
+            n--;
+        }
+
+        return nCount;
+    }
+    else
+        return 0;
+}
+
+void SvpSalInstance::AcquireYieldMutex( sal_uLong nCount )
+{
+    while ( nCount )
+    {
+        m_aYieldMutex.acquire();
+        nCount--;
+    }
+}
+
+bool SvpSalInstance::CheckYieldMutex()
+{
+    bool bRet = true;
+
+    if ( m_aYieldMutex.GetThreadId() != ::osl::Thread::getCurrentIdentifier() )
+    {
+        bRet = false;
+    }
+
+    return bRet;
+}
+
+void SvpSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
+{
+    // first, check for already queued events.
+
+    // release yield mutex
+    std::list< SalUserEvent > aEvents;
+    sal_uLong nAcquireCount = ReleaseYieldMutex();
+    if( osl_acquireMutex( m_aEventGuard ) )
+    {
+        if( ! m_aUserEvents.empty() )
+        {
+            if( bHandleAllCurrentEvents )
+            {
+                aEvents = m_aUserEvents;
+                m_aUserEvents.clear();
+            }
+            else
+            {
+                aEvents.push_back( m_aUserEvents.front() );
+                m_aUserEvents.pop_front();
+            }
+        }
+        osl_releaseMutex( m_aEventGuard );
+    }
+    // acquire yield mutex again
+    AcquireYieldMutex( nAcquireCount );
+
+    bool bEvent = !aEvents.empty();
+    if( bEvent )
+    {
+        for( std::list<SalUserEvent>::const_iterator it = aEvents.begin(); it != aEvents.end(); ++it )
+        {
+            if ( isFrameAlive( it->m_pFrame ) )
+            {
+                it->m_pFrame->CallCallback( it->m_nEvent, it->m_pData );
+                if( it->m_nEvent == SALEVENT_RESIZE )
+                {
+                    // this would be a good time to post a paint
+                    const SvpSalFrame* pSvpFrame = static_cast<const SvpSalFrame*>(it->m_pFrame);
+                    pSvpFrame->PostPaint();
+                }
+            }
+        }
+    }
+
+    bEvent = CheckTimeout() || bEvent;
+
+    if (bWait && ! bEvent )
+    {
+        int nTimeoutMS = 0;
+        if (m_aTimeout.tv_sec) // Timer is started.
+        {
+            timeval Timeout;
+            // determine remaining timeout.
+            gettimeofday (&Timeout, 0);
+            nTimeoutMS = m_aTimeout.tv_sec*1000 + m_aTimeout.tv_usec/1000
+                         - Timeout.tv_sec*1000 - Timeout.tv_usec/1000;
+            if( nTimeoutMS < 0 )
+                nTimeoutMS = 0;
+        }
+        else
+            nTimeoutMS = -1; // wait until something happens
+
+        // release yield mutex
+        nAcquireCount = ReleaseYieldMutex();
+        // poll
+        struct pollfd aPoll;
+        aPoll.fd = m_pTimeoutFDS[0];
+        aPoll.events = POLLIN;
+        aPoll.revents = 0;
+        poll( &aPoll, 1, nTimeoutMS );
+
+        // acquire yield mutex again
+        AcquireYieldMutex( nAcquireCount );
+
+        // clean up pipe
+        if( (aPoll.revents & POLLIN) != 0 )
+        {
+            int buffer;
+            while (read (m_pTimeoutFDS[0], &buffer, sizeof(buffer)) > 0)
+                continue;
+        }
+    }
+}
+
+bool SvpSalInstance::AnyInput( sal_uInt16 nType )
+{
+    if( (nType & INPUT_TIMER) != 0 )
+        return CheckTimeout( false );
+    return false;
+}
+
+SalSession* SvpSalInstance::CreateSalSession()
+{
+    return NULL;
+}
+
+void* SvpSalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes )
+{
+    rReturnedBytes  = 1;
+    rReturnedType   = AsciiCString;
+    return const_cast<char*>("");
+}
+
+// -------------------------------------------------------------------------
+//
+// SalYieldMutex
+//
+// -------------------------------------------------------------------------
+
+SvpSalYieldMutex::SvpSalYieldMutex()
+{
+    mnCount     = 0;
+    mnThreadId  = 0;
+}
+
+void SvpSalYieldMutex::acquire()
+{
+    SolarMutexObject::acquire();
+    mnThreadId = osl::Thread::getCurrentIdentifier();
+    mnCount++;
+}
+
+void SvpSalYieldMutex::release()
+{
+    if ( mnThreadId == osl::Thread::getCurrentIdentifier() )
+    {
+        if ( mnCount == 1 )
+            mnThreadId = 0;
+        mnCount--;
+    }
+    SolarMutexObject::release();
+}
+
+sal_Bool SvpSalYieldMutex::tryToAcquire()
+{
+    if ( SolarMutexObject::tryToAcquire() )
+    {
+        mnThreadId = osl::Thread::getCurrentIdentifier();
+        mnCount++;
+        return sal_True;
+    }
+    else
+        return sal_False;
+}
+
+// ---------------
+// - SalTimer -
+// ---------------
+
+void SvpSalInstance::StopTimer()
+{
+    m_aTimeout.tv_sec   = 0;
+    m_aTimeout.tv_usec  = 0;
+    m_nTimeoutMS        = 0;
+}
+
+void SvpSalInstance::StartTimer( sal_uLong nMS )
+{
+    timeval Timeout (m_aTimeout); // previous timeout.
+    gettimeofday (&m_aTimeout, 0);
+
+    m_nTimeoutMS  = nMS;
+    m_aTimeout    += m_nTimeoutMS;
+
+    if ((Timeout > m_aTimeout) || (Timeout.tv_sec == 0))
+    {
+        // Wakeup from previous timeout (or stopped timer).
+        Wakeup();
+    }
+}
+
+void SvpSalInstance::AddToRecentDocumentList(const rtl::OUString&, const rtl::OUString&)
+{
+}
+
+SvpSalTimer::~SvpSalTimer()
+{
+}
+
+void SvpSalTimer::Stop()
+{
+    m_pInstance->StopTimer();
+}
+
+void SvpSalTimer::Start( sal_uLong nMS )
+{
+    m_pInstance->StartTimer( nMS );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/headless/svpprn.cxx b/vcl/headless/svpprn.cxx
new file mode 100644
index 0000000..452f8ab
--- /dev/null
+++ b/vcl/headless/svpprn.cxx
@@ -0,0 +1,322 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include "vcl/svapp.hxx"
+#include "vcl/timer.hxx"
+#include "vcl/printerinfomanager.hxx"
+
+#include "jobset.h"
+#include "print.h"
+#include "salptype.hxx"
+#include "saldatabasic.hxx"
+
+#include "headless/svpprn.hxx"
+#include "headless/svppspgraphics.hxx"
+#include "headless/svpinst.hxx"
+
+using namespace psp;
+
+using ::rtl::OUString;
+using ::rtl::OUStringToOString;
+
+/*
+ *  static helpers
+ */
+
+static String getPdfDir( const PrinterInfo& rInfo )
+{
+    String aDir;
+    sal_Int32 nIndex = 0;
+    while( nIndex != -1 )
+    {
+        OUString aToken( rInfo.m_aFeatures.getToken( 0, ',', nIndex ) );
+        if( ! aToken.compareToAscii( "pdf=", 4 ) )
+        {
+            sal_Int32 nPos = 0;
+            aDir = aToken.getToken( 1, '=', nPos );
+            if( ! aDir.Len() )
+                aDir = String( ByteString( getenv( "HOME" ) ), osl_getThreadTextEncoding() );
+            break;
+        }
+    }
+    return aDir;
+}
+
+inline int PtTo10Mu( int nPoints ) { return (int)((((double)nPoints)*35.27777778)+0.5); }
+
+inline int TenMuToPt( int nUnits ) { return (int)((((double)nUnits)/35.27777778)+0.5); }
+
+static void copyJobDataToJobSetup( ImplJobSetup* pJobSetup, JobData& rData )
+{
+    pJobSetup->meOrientation    = (Orientation)(rData.m_eOrientation == orientation::Landscape ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT);
+
+    // copy page size
+    String aPaper;
+    int width, height;
+
+    rData.m_aContext.getPageSize( aPaper, width, height );
+    pJobSetup->mePaperFormat    = PaperInfo::fromPSName(OUStringToOString( aPaper, RTL_TEXTENCODING_ISO_8859_1 ));
+    pJobSetup->mnPaperWidth     = 0;
+    pJobSetup->mnPaperHeight    = 0;
+    if( pJobSetup->mePaperFormat == PAPER_USER )
+    {
+        // transform to 100dth mm
+        width               = PtTo10Mu( width );
+        height              = PtTo10Mu( height );
+
+        if( rData.m_eOrientation == psp::orientation::Portrait )
+        {
+            pJobSetup->mnPaperWidth = width;
+            pJobSetup->mnPaperHeight= height;
+        }
+        else
+        {
+            pJobSetup->mnPaperWidth = height;
+            pJobSetup->mnPaperHeight= width;
+        }
+    }
+
+    // copy input slot
+    const PPDKey* pKey = NULL;
+    const PPDValue* pValue = NULL;
+
+    pJobSetup->mnPaperBin = 0xffff;
+    if( rData.m_pParser )
+        pKey                    = rData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "InputSlot" ) ) );
+    if( pKey )
+        pValue                  = rData.m_aContext.getValue( pKey );
+    if( pKey && pValue )
+    {
+        for( pJobSetup->mnPaperBin = 0;
+             pValue != pKey->getValue( pJobSetup->mnPaperBin ) &&
+                 pJobSetup->mnPaperBin < pKey->countValues();
+             pJobSetup->mnPaperBin++ )
+            ;
+        if( pJobSetup->mnPaperBin >= pKey->countValues() || pValue == pKey->getDefaultValue() )
+            pJobSetup->mnPaperBin = 0xffff;
+    }
+
+    // copy duplex
+    pKey = NULL;
+    pValue = NULL;
+
+    pJobSetup->meDuplexMode = DUPLEX_UNKNOWN;
+    if( rData.m_pParser )
+        pKey = rData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "Duplex" ) ) );
+    if( pKey )
+        pValue = rData.m_aContext.getValue( pKey );
+    if( pKey && pValue )
+    {
+        if( pValue->m_aOption.EqualsIgnoreCaseAscii( "None" ) ||
+            pValue->m_aOption.EqualsIgnoreCaseAscii( "Simplex", 0, 7 )
+           )
+        {
+            pJobSetup->meDuplexMode = DUPLEX_OFF;
+        }
+        else if( pValue->m_aOption.EqualsIgnoreCaseAscii( "DuplexNoTumble" ) )
+        {
+            pJobSetup->meDuplexMode = DUPLEX_LONGEDGE;
+        }
+        else if( pValue->m_aOption.EqualsIgnoreCaseAscii( "DuplexTumble" ) )
+        {
+            pJobSetup->meDuplexMode = DUPLEX_SHORTEDGE;
+        }
+    }
+
+    // copy the whole context
+    if( pJobSetup->mpDriverData )
+        rtl_freeMemory( pJobSetup->mpDriverData );
+
+    int nBytes;
+    void* pBuffer = NULL;
+    if( rData.getStreamBuffer( pBuffer, nBytes ) )
+    {
+        pJobSetup->mnDriverDataLen = nBytes;
+        pJobSetup->mpDriverData = (sal_uInt8*)pBuffer;
+    }
+    else
+    {
+        pJobSetup->mnDriverDataLen = 0;
+        pJobSetup->mpDriverData = NULL;
+    }
+}
+
+/*
+ *  SalInstance
+ */
+
+// -----------------------------------------------------------------------
+
+SalInfoPrinter* SvpSalInstance::CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo,
+                                                   ImplJobSetup*            pJobSetup )
+{
+    // create and initialize SalInfoPrinter
+    SvpSalInfoPrinter* pPrinter = new SvpSalInfoPrinter;
+
+    if( pJobSetup )
+    {
+        PrinterInfoManager& rManager( PrinterInfoManager::get() );
+        PrinterInfo aInfo( rManager.getPrinterInfo( pQueueInfo->maPrinterName ) );
+        pPrinter->m_aJobData = aInfo;
+        pPrinter->m_aPrinterGfx.Init( pPrinter->m_aJobData );
+
+        if( pJobSetup->mpDriverData )
+            JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aInfo );
+
+        pJobSetup->mnSystem         = JOBSETUP_SYSTEM_UNIX;
+        pJobSetup->maPrinterName    = pQueueInfo->maPrinterName;
+        pJobSetup->maDriver         = aInfo.m_aDriverName;
+        copyJobDataToJobSetup( pJobSetup, aInfo );
+
+        // set/clear backwards compatibility flag
+        bool bStrictSO52Compatibility = false;
+        boost::unordered_map<rtl::OUString, rtl::OUString, rtl::OUStringHash >::const_iterator compat_it =
+            pJobSetup->maValueMap.find( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StrictSO52Compatibility" ) ) );
+        if( compat_it != pJobSetup->maValueMap.end() )
+        {
+            if( compat_it->second.equalsIgnoreAsciiCaseAscii( "true" ) )
+                bStrictSO52Compatibility = true;
+        }
+        pPrinter->m_aPrinterGfx.setStrictSO52Compatibility( bStrictSO52Compatibility );
+    }
+
+
+    return pPrinter;
+}
+
+// -----------------------------------------------------------------------
+
+void SvpSalInstance::DestroyInfoPrinter( SalInfoPrinter* pPrinter )
+{
+    delete pPrinter;
+}
+
+// -----------------------------------------------------------------------
+
+SalPrinter* SvpSalInstance::CreatePrinter( SalInfoPrinter* pInfoPrinter )
+{
+    // create and initialize SalPrinter
+    SvpSalPrinter* pPrinter = new SvpSalPrinter( pInfoPrinter );
+    pPrinter->m_aJobData = static_cast<SvpSalInfoPrinter*>(pInfoPrinter)->m_aJobData;
+
+    return pPrinter;
+}
+
+// -----------------------------------------------------------------------
+
+void SvpSalInstance::DestroyPrinter( SalPrinter* pPrinter )
+{
+    delete pPrinter;
+}
+
+// -----------------------------------------------------------------------
+
+void SvpSalInstance::GetPrinterQueueInfo( ImplPrnQueueList* pList )
+{
+    PrinterInfoManager& rManager( PrinterInfoManager::get() );
+    static const char* pNoSyncDetection = getenv( "SAL_DISABLE_SYNCHRONOUS_PRINTER_DETECTION" );
+    if( ! pNoSyncDetection || ! *pNoSyncDetection )
+    {
+        // #i62663# synchronize possible asynchronouse printer detection now
+        rManager.checkPrintersChanged( true );
+    }
+    ::std::list< OUString > aPrinters;
+    rManager.listPrinters( aPrinters );
+
+    for( ::std::list< OUString >::iterator it = aPrinters.begin(); it != aPrinters.end(); ++it )
+    {
+        const PrinterInfo& rInfo( rManager.getPrinterInfo( *it ) );
+        // Neuen Eintrag anlegen
+        SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo;
+        pInfo->maPrinterName    = *it;
+        pInfo->maDriver         = rInfo.m_aDriverName;
+        pInfo->maLocation       = rInfo.m_aLocation;
+        pInfo->maComment        = rInfo.m_aComment;
+        pInfo->mpSysData        = NULL;
+
+        sal_Int32 nIndex = 0;
+        while( nIndex != -1 )
+        {
+            String aToken( rInfo.m_aFeatures.getToken( 0, ',', nIndex ) );
+            if( aToken.CompareToAscii( "pdf=", 4 ) == COMPARE_EQUAL )
+            {
+                pInfo->maLocation = getPdfDir( rInfo );
+                break;
+            }
+        }
+
+        pList->Add( pInfo );
+    }
+}
+
+// -----------------------------------------------------------------------
+
+void SvpSalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo )
+{
+    delete pInfo;
+}
+
+// -----------------------------------------------------------------------
+
+void SvpSalInstance::GetPrinterQueueState( SalPrinterQueueInfo* )
+{
+}
+
+// -----------------------------------------------------------------------
+
+String SvpSalInstance::GetDefaultPrinter()
+{
+    PrinterInfoManager& rManager( PrinterInfoManager::get() );
+    return rManager.getDefaultPrinter();
+}
+
+// -----------------------------------------------------------------------
+
+void SvpSalInstance::PostPrintersChanged()
+{
+    const std::list< SalFrame* >& rList = SvpSalInstance::s_pDefaultInstance->getFrames();
+    for( std::list< SalFrame* >::const_iterator it = rList.begin();
+         it != rList.end(); ++it )
+        SvpSalInstance::s_pDefaultInstance->PostEvent( *it, NULL, SALEVENT_PRINTERCHANGED );
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool SvpSalInfoPrinter::Setup( SalFrame*, ImplJobSetup* )
+{
+    return sal_False;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/headless/svppspgraphics.cxx b/vcl/headless/svppspgraphics.cxx
new file mode 100644
index 0000000..5a79253
--- /dev/null
+++ b/vcl/headless/svppspgraphics.cxx
@@ -0,0 +1,1302 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "basegfx/vector/b2ivector.hxx"
+#include "basegfx/point/b2ipoint.hxx"
+
+#include "basebmp/color.hxx"
+
+#include "vcl/jobdata.hxx"
+#include "vcl/printerinfomanager.hxx"
+#include "vcl/bmpacc.hxx"
+#include "vcl/svapp.hxx"
+#include "vcl/sysdata.hxx"
+
+#include "salprn.hxx"
+#include "salbmp.hxx"
+#include "impfont.hxx"
+#include "outfont.hxx"
+#include "fontsubset.hxx"
+#include "generic/printergfx.hxx"
+#include "headless/svppspgraphics.hxx"
+#include "headless/svpbmp.hxx"
+#include "generic/glyphcache.hxx"
+#include "region.h"
+
+using namespace psp;
+using namespace basebmp;
+using namespace basegfx;
+using ::rtl::OUString;
+using ::rtl::OString;
+// ----- Implementation of PrinterBmp by means of SalBitmap/BitmapBuffer ---------------
+
+class SalPrinterBmp : public psp::PrinterBmp
+{
+    private:
+    SalPrinterBmp ();
+
+    BitmapDeviceSharedPtr       m_aBitmap;
+    public:
+
+                            SalPrinterBmp (const BitmapDeviceSharedPtr& rDevice);
+        virtual             ~SalPrinterBmp ();
+        virtual sal_uInt32  GetPaletteColor (sal_uInt32 nIdx) const;
+        virtual sal_uInt32  GetPaletteEntryCount () const;
+        virtual sal_uInt32  GetPixelRGB  (sal_uInt32 nRow, sal_uInt32 nColumn) const;
+        virtual sal_uInt8   GetPixelGray (sal_uInt32 nRow, sal_uInt32 nColumn) const;
+        virtual sal_uInt8   GetPixelIdx  (sal_uInt32 nRow, sal_uInt32 nColumn) const;
+        virtual sal_uInt32  GetWidth () const;
+        virtual sal_uInt32  GetHeight() const;
+        virtual sal_uInt32  GetDepth () const;
+
+        static sal_uInt32 getRGBFromColor( const basebmp::Color& rCol )
+        {
+            return    ((rCol.getBlue())          & 0x000000ff)
+                    | ((rCol.getGreen() <<  8) & 0x0000ff00)
+                    | ((rCol.getRed()   << 16) & 0x00ff0000);
+        }
+};
+
+SalPrinterBmp::SalPrinterBmp(const BitmapDeviceSharedPtr& rDevice) :
+    m_aBitmap( rDevice )
+{
+}
+
+SalPrinterBmp::~SalPrinterBmp ()
+{
+}
+
+sal_uInt32
+SalPrinterBmp::GetWidth () const
+{
+    return m_aBitmap.get() ? m_aBitmap->getSize().getX() : 0;
+}
+
+sal_uInt32
+SalPrinterBmp::GetHeight () const
+{
+    return m_aBitmap.get() ? m_aBitmap->getSize().getY() : 0;
+}
+
+sal_uInt32
+SalPrinterBmp::GetDepth () const
+{
+    return m_aBitmap.get() ?
+           SvpElement::getBitCountFromScanlineFormat( m_aBitmap->getScanlineFormat() )
+           : 0;
+}
+
+
+sal_uInt32
+SalPrinterBmp::GetPaletteEntryCount () const
+{
+    return m_aBitmap.get() ? m_aBitmap->getPaletteEntryCount() : 0;
+}
+
+sal_uInt32
+SalPrinterBmp::GetPaletteColor (sal_uInt32 nIdx) const
+{
+    sal_uInt32 nCol = 0;
+    if( m_aBitmap.get() && nIdx < static_cast<sal_uInt32>(m_aBitmap->getPaletteEntryCount()) )
+    {
+        const basebmp::Color& rColor = (*m_aBitmap->getPalette().get())[ nIdx ];
+        nCol = getRGBFromColor( rColor );
+    }
+    return nCol;
+}
+
+sal_uInt32
+SalPrinterBmp::GetPixelRGB (sal_uInt32 nRow, sal_uInt32 nColumn) const
+{
+    sal_uInt32 nCol = 0;
+    if( m_aBitmap.get() )
+        nCol = getRGBFromColor( m_aBitmap->getPixel( B2IPoint( nColumn, nRow ) ) );
+    return nCol;
+}
+
+sal_uInt8
+SalPrinterBmp::GetPixelGray (sal_uInt32 nRow, sal_uInt32 nColumn) const
+{
+    sal_uInt8 nGray = 0;
+    if( m_aBitmap.get() )
+    {
+        // TODO: don't use tools color
+        basebmp::Color aCol = m_aBitmap->getPixel( B2IPoint( nColumn, nRow ) );
+        ::Color aColor( aCol.getRed(), aCol.getGreen(), aCol.getBlue() );
+        nGray = aColor.GetLuminance();
+    }
+    return nGray;
+}
+
+sal_uInt8
+SalPrinterBmp::GetPixelIdx (sal_uInt32 nRow, sal_uInt32 nColumn) const
+{
+    sal_uInt8 nIdx = 0;
+    if( m_aBitmap.get() )
+        nIdx = static_cast<sal_uInt8>(m_aBitmap->getPixelData( B2IPoint( nColumn, nRow ) ));
+    return nIdx;
+}
+
+/*******************************************************
+ * PspGraphics                                         *
+ *******************************************************/
+
+bool PspGraphics::drawAlphaBitmap( const SalTwoRect&, const SalBitmap& /*rSourceBitmap*/, const SalBitmap& /*rAlphaBitmap*/ )
+{
+    return false;
+}
+
+bool PspGraphics::drawAlphaRect( long /*nX*/, long /*nY*/, long /*nWidth*/, long /*nHeight*/, sal_uInt8 /*nTransparency*/ )
+{
+    return false;
+}
+
+bool PspGraphics::supportsOperation( OutDevSupportType ) const
+{
+    return false;
+}
+
+PspGraphics::~PspGraphics()
+{
+    ReleaseFonts();
+}
+
+void PspGraphics::GetResolution( sal_Int32 &rDPIX, sal_Int32 &rDPIY )
+{
+    if (m_pJobData != NULL)
+    {
+        int x = m_pJobData->m_aContext.getRenderResolution();
+
+        rDPIX = x;
+        rDPIY = x;
+    }
+}
+
+sal_uInt16 PspGraphics::GetBitCount() const
+{
+    return m_pPrinterGfx->GetBitCount();
+}
+
+long PspGraphics::GetGraphicsWidth() const
+{
+    return 0;
+}
+
+void PspGraphics::ResetClipRegion()
+{
+    m_pPrinterGfx->ResetClipRegion();
+}
+
+bool PspGraphics::setClipRegion( const Region& i_rClip )
+{
+    // TODO: support polygonal clipregions here
+    m_pPrinterGfx->BeginSetClipRegion( i_rClip.GetRectCount() );
+
+    ImplRegionInfo aInfo;
+    long nX, nY, nW, nH;
+    bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH );
+    while( bRegionRect )
+    {
+        if ( nW && nH )
+        {
+            m_pPrinterGfx->UnionClipRegion( nX, nY, nW, nH );
+        }
+        bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH );
+    }
+    m_pPrinterGfx->EndSetClipRegion();
+    return true;
+}
+
+void PspGraphics::SetLineColor()
+{
+    m_pPrinterGfx->SetLineColor ();
+}
+
+void PspGraphics::SetLineColor( SalColor nSalColor )
+{
+    psp::PrinterColor aColor (SALCOLOR_RED   (nSalColor),
+                              SALCOLOR_GREEN (nSalColor),
+                              SALCOLOR_BLUE  (nSalColor));
+    m_pPrinterGfx->SetLineColor (aColor);
+}
+
+void PspGraphics::SetFillColor()
+{
+    m_pPrinterGfx->SetFillColor ();
+}
+
+void PspGraphics::SetFillColor( SalColor nSalColor )
+{
+    psp::PrinterColor aColor (SALCOLOR_RED   (nSalColor),
+                              SALCOLOR_GREEN (nSalColor),
+                              SALCOLOR_BLUE  (nSalColor));
+    m_pPrinterGfx->SetFillColor (aColor);
+}
+
+void PspGraphics::SetROPLineColor( SalROPColor )
+{
+    DBG_ASSERT( 0, "Error: PrinterGfx::SetROPLineColor() not implemented" );
+}
+
+void PspGraphics::SetROPFillColor( SalROPColor )
+{
+    DBG_ASSERT( 0, "Error: PrinterGfx::SetROPFillColor() not implemented" );
+}
+
+void PspGraphics::SetXORMode( bool bSet, bool )

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list