зеркало из https://github.com/mozilla/pjs.git
Bug 544250 - Implement different rendering backends for Qt mozilla port. r=jmuizelaar.
This commit is contained in:
Родитель
b3ac46a92d
Коммит
4b8146c17f
|
@ -32,6 +32,10 @@ EXPORTS = gfxASurface.h \
|
|||
gfxUserFontSet.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS += \
|
||||
gfxSharedImageSurface.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS += gfxFontTest.h
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
|
||||
|
|
|
@ -51,6 +51,18 @@ class FontEntry;
|
|||
|
||||
class THEBES_API gfxQtPlatform : public gfxPlatform {
|
||||
public:
|
||||
|
||||
enum RenderMode {
|
||||
/* Use QPainter surfaces */
|
||||
RENDER_QPAINTER = 0,
|
||||
/* Use Xlib surface to render and wrap as QPixmap */
|
||||
RENDER_XLIB,
|
||||
/* Use image surfaces and XShmPutImage to QPixmap */
|
||||
RENDER_SHARED_IMAGE,
|
||||
/* max */
|
||||
RENDER_MODE_MAX
|
||||
};
|
||||
|
||||
gfxQtPlatform();
|
||||
virtual ~gfxQtPlatform();
|
||||
|
||||
|
@ -87,6 +99,9 @@ public:
|
|||
|
||||
FT_Library GetFTLibrary();
|
||||
|
||||
RenderMode GetRenderMode() { return mRenderMode; }
|
||||
void SetRenderMode(RenderMode rmode) { mRenderMode = rmode; }
|
||||
|
||||
protected:
|
||||
static gfxFontconfigUtils *sFontconfigUtils;
|
||||
|
||||
|
@ -96,6 +111,7 @@ private:
|
|||
// TODO: unify this with mPrefFonts (NB: holds families, not fonts) in gfxPlatformFontList
|
||||
nsDataHashtable<nsCStringHashKey, nsTArray<nsRefPtr<gfxFontEntry> > > mPrefFonts;
|
||||
|
||||
RenderMode mRenderMode;
|
||||
};
|
||||
|
||||
#endif /* GFX_PLATFORM_QT_H */
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Nokia Corporation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Nokia Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2005
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Oleg Romashin <romaxa@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef GFX_SHARED_IMAGESURFACE_H
|
||||
#define GFX_SHARED_IMAGESURFACE_H
|
||||
|
||||
#ifdef MOZ_X11
|
||||
#ifdef HAVE_XSHM
|
||||
|
||||
#include "gfxASurface.h"
|
||||
#include "gfxImageSurface.h"
|
||||
#include "gfxPoint.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef MOZ_WIDGET_QT
|
||||
#include <QX11Info>
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GTK2
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_X11
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
#endif
|
||||
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
|
||||
class THEBES_API gfxSharedImageSurface : public gfxASurface {
|
||||
public:
|
||||
gfxSharedImageSurface();
|
||||
~gfxSharedImageSurface();
|
||||
|
||||
// ImageSurface methods
|
||||
gfxImageFormat Format() const { return mFormat; }
|
||||
|
||||
const gfxIntSize& GetSize() const { return mSize; }
|
||||
int Width() const { return mSize.width; }
|
||||
int Height() const { return mSize.height; }
|
||||
|
||||
/**
|
||||
* Distance in bytes between the start of a line and the start of the
|
||||
* next line.
|
||||
*/
|
||||
int Stride() const { return mStride; }
|
||||
|
||||
/**
|
||||
* Returns a pointer for the image data. Users of this function can
|
||||
* write to it, but must not attempt to free the buffer.
|
||||
*/
|
||||
unsigned char* Data() const { return mData; } // delete this data under us and die.
|
||||
|
||||
/**
|
||||
* Returns the total size of the image data.
|
||||
*/
|
||||
int GetDataSize() const { return mStride*mSize.height; }
|
||||
|
||||
/**
|
||||
* Returns a pointer for the X-image structure.
|
||||
*/
|
||||
XImage *image() const { return mXShmImage; }
|
||||
|
||||
/**
|
||||
* Returns a gfxImageSurface as gfxASurface.
|
||||
*/
|
||||
already_AddRefed<gfxASurface> getASurface(void);
|
||||
|
||||
/**
|
||||
* Construct an shared image surface and XImage
|
||||
* @param aSize The size of the buffer
|
||||
* @param aFormat Format of the data
|
||||
* @see gfxImageFormat
|
||||
* @param aShmId Shared Memory ID of data created outside,
|
||||
* if not specified, then class will allocate own shared memory
|
||||
* @display aDisplay display used for X-Image creation
|
||||
* if not specified, then used system default
|
||||
*
|
||||
*/
|
||||
bool Init(const gfxIntSize& aSize,
|
||||
gfxImageFormat aFormat = ImageFormatUnknown,
|
||||
int aShmId = -1,
|
||||
Display *aDisplay = NULL);
|
||||
|
||||
private:
|
||||
bool CreateInternal(int aShmid);
|
||||
long ComputeStride() const;
|
||||
inline bool ComputeDepth();
|
||||
inline bool ComputeFormat();
|
||||
|
||||
unsigned int mDepth;
|
||||
int mShmId;
|
||||
|
||||
gfxIntSize mSize;
|
||||
bool mOwnsData;
|
||||
|
||||
unsigned char *mData;
|
||||
gfxImageFormat mFormat;
|
||||
long mStride;
|
||||
|
||||
Display *mDisp;
|
||||
XShmSegmentInfo mShmInfo;
|
||||
XImage *mXShmImage;
|
||||
};
|
||||
|
||||
#endif /* HAVE_XSHM */
|
||||
#endif /* MOZ_X11 */
|
||||
#endif /* GFX_SHARED_IMAGESURFACE_H */
|
|
@ -34,6 +34,10 @@ CPPSRCS = \
|
|||
gfxUserFontSet.cpp \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS += \
|
||||
gfxSharedImageSurface.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DSO_LDOPTS += \
|
||||
$(MOZ_CAIRO_LIBS) \
|
||||
$(MOZ_UNICHARUTIL_LIBS) \
|
||||
|
|
|
@ -58,12 +58,20 @@
|
|||
|
||||
#include "nsMathUtils.h"
|
||||
#include "nsTArray.h"
|
||||
#ifdef MOZ_X11
|
||||
#include "gfxXlibSurface.h"
|
||||
#endif
|
||||
|
||||
#include "qcms.h"
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIPrefService.h"
|
||||
|
||||
#define DEFAULT_RENDER_MODE RENDER_SHARED_IMAGE
|
||||
|
||||
gfxFontconfigUtils *gfxQtPlatform::sFontconfigUtils = nsnull;
|
||||
static cairo_user_data_key_t cairo_qt_pixmap_key;
|
||||
static void do_qt_pixmap_unref (void *data)
|
||||
|
@ -99,6 +107,36 @@ gfxQtPlatform::gfxQtPlatform()
|
|||
gPrefFonts->Init(100);
|
||||
gCodepointsWithNoFonts = new gfxSparseBitSet();
|
||||
UpdateFontList();
|
||||
|
||||
nsresult rv;
|
||||
PRInt32 ival;
|
||||
// 0 - default gfxQPainterSurface
|
||||
// 1 - gfxXlibSurface
|
||||
// 2 - gfxImageSurface
|
||||
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
|
||||
if (prefs) {
|
||||
rv = prefs->GetIntPref("mozilla.widget-qt.render-mode", &ival);
|
||||
if (NS_FAILED(rv))
|
||||
ival = DEFAULT_RENDER_MODE;
|
||||
}
|
||||
|
||||
const char *envTypeOverride = getenv("MOZ_QT_RENDER_TYPE");
|
||||
if (envTypeOverride)
|
||||
ival = atoi(envTypeOverride);
|
||||
|
||||
switch (ival) {
|
||||
case 0:
|
||||
mRenderMode = RENDER_QPAINTER;
|
||||
break;
|
||||
case 1:
|
||||
mRenderMode = RENDER_XLIB;
|
||||
break;
|
||||
case 2:
|
||||
mRenderMode = RENDER_SHARED_IMAGE;
|
||||
break;
|
||||
default:
|
||||
mRenderMode = RENDER_QPAINTER;
|
||||
}
|
||||
}
|
||||
|
||||
gfxQtPlatform::~gfxQtPlatform()
|
||||
|
@ -134,8 +172,53 @@ already_AddRefed<gfxASurface>
|
|||
gfxQtPlatform::CreateOffscreenSurface(const gfxIntSize& size,
|
||||
gfxASurface::gfxImageFormat imageFormat)
|
||||
{
|
||||
nsRefPtr<gfxASurface> newSurface =
|
||||
new gfxQPainterSurface (size, gfxASurface::ContentFromFormat(imageFormat));
|
||||
nsRefPtr<gfxASurface> newSurface = nsnull;
|
||||
|
||||
if (mRenderMode == RENDER_QPAINTER) {
|
||||
newSurface = new gfxQPainterSurface(size, gfxASurface::ContentFromFormat(imageFormat));
|
||||
return newSurface.forget();
|
||||
}
|
||||
|
||||
if (mRenderMode == RENDER_SHARED_IMAGE) {
|
||||
newSurface = new gfxImageSurface(size, imageFormat);
|
||||
return newSurface.forget();
|
||||
}
|
||||
|
||||
#ifdef MOZ_X11
|
||||
int xrenderFormatID = -1;
|
||||
switch (imageFormat) {
|
||||
case gfxASurface::ImageFormatARGB32:
|
||||
xrenderFormatID = PictStandardARGB32;
|
||||
break;
|
||||
case gfxASurface::ImageFormatRGB24:
|
||||
xrenderFormatID = PictStandardRGB24;
|
||||
break;
|
||||
case gfxASurface::ImageFormatA8:
|
||||
xrenderFormatID = PictStandardA8;
|
||||
break;
|
||||
case gfxASurface::ImageFormatA1:
|
||||
xrenderFormatID = PictStandardA1;
|
||||
break;
|
||||
default:
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// XXX we really need a different interface here, something that passes
|
||||
// in more context, including the display and/or target surface type that
|
||||
// we should try to match
|
||||
XRenderPictFormat* xrenderFormat =
|
||||
XRenderFindStandardFormat(QX11Info().display(), xrenderFormatID);
|
||||
|
||||
newSurface = new gfxXlibSurface((Display*)QX11Info().display(),
|
||||
xrenderFormat,
|
||||
size);
|
||||
#endif
|
||||
|
||||
if (newSurface) {
|
||||
gfxContext ctx(newSurface);
|
||||
ctx.SetOperator(gfxContext::OPERATOR_CLEAR);
|
||||
ctx.Paint();
|
||||
}
|
||||
|
||||
return newSurface.forget();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,240 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Nokia Corporation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Nokia Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2005
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Oleg Romashin <romaxa@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "gfxSharedImageSurface.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef MOZ_X11
|
||||
#ifdef HAVE_XSHM
|
||||
|
||||
gfxSharedImageSurface::gfxSharedImageSurface()
|
||||
: mDepth(0),
|
||||
mShmId(0),
|
||||
mOwnsData(true),
|
||||
mData(NULL),
|
||||
mStride(0),
|
||||
mXShmImage(NULL)
|
||||
{
|
||||
memset(&mShmInfo, 0, sizeof(XShmSegmentInfo));
|
||||
}
|
||||
|
||||
gfxSharedImageSurface::~gfxSharedImageSurface()
|
||||
{
|
||||
// Finish all pending XServer operations
|
||||
if (mDisp) {
|
||||
XSync(mDisp, False);
|
||||
XShmDetach(mDisp, &mShmInfo);
|
||||
}
|
||||
|
||||
if (mData)
|
||||
shmdt(mData);
|
||||
|
||||
if (mXShmImage)
|
||||
XDestroyImage(mXShmImage);
|
||||
}
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
gfxSharedImageSurface::getASurface(void)
|
||||
{
|
||||
NS_ENSURE_TRUE(mData, NULL);
|
||||
|
||||
gfxASurface::gfxImageFormat imageFormat = gfxASurface::ImageFormatRGB24;
|
||||
if (mDepth == 32)
|
||||
imageFormat = gfxASurface::ImageFormatARGB32;
|
||||
|
||||
gfxASurface* result = new gfxImageSurface(mData, mSize, mStride, imageFormat);
|
||||
NS_IF_ADDREF(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_QT
|
||||
static unsigned int
|
||||
getSystemDepth()
|
||||
{
|
||||
return QX11Info::appDepth();
|
||||
}
|
||||
|
||||
static Display*
|
||||
getSystemDisplay()
|
||||
{
|
||||
return QX11Info::display();
|
||||
}
|
||||
#endif
|
||||
#ifdef MOZ_WIDGET_GTK2
|
||||
static unsigned int
|
||||
getSystemDepth()
|
||||
{
|
||||
return gdk_visual_get_system()->depth;
|
||||
}
|
||||
|
||||
static Display*
|
||||
getSystemDisplay()
|
||||
{
|
||||
return GDK_DISPLAY();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
bool
|
||||
gfxSharedImageSurface::Init(const gfxIntSize& aSize,
|
||||
gfxImageFormat aFormat,
|
||||
int aShmId,
|
||||
Display *aDisplay)
|
||||
{
|
||||
mSize = aSize;
|
||||
|
||||
if (aFormat != ImageFormatUnknown) {
|
||||
mFormat = aFormat;
|
||||
if (!ComputeDepth())
|
||||
return false;
|
||||
} else {
|
||||
mDepth = getSystemDepth();
|
||||
if (!ComputeFormat())
|
||||
NS_WARNING("Will work with system depth");
|
||||
}
|
||||
|
||||
mDisp = aDisplay ? aDisplay : getSystemDisplay();
|
||||
if (!mDisp)
|
||||
return false;
|
||||
|
||||
return CreateInternal(aShmId);
|
||||
}
|
||||
|
||||
bool
|
||||
gfxSharedImageSurface::CreateInternal(int aShmid)
|
||||
{
|
||||
memset(&mShmInfo, 0, sizeof(mShmInfo));
|
||||
|
||||
mStride = ComputeStride();
|
||||
|
||||
if (aShmid != -1) {
|
||||
mShmId = aShmid;
|
||||
mOwnsData = false;
|
||||
} else
|
||||
mShmId = shmget(IPC_PRIVATE, GetDataSize(), IPC_CREAT | 0777);
|
||||
|
||||
if (mShmId == -1)
|
||||
return false;
|
||||
|
||||
void *data = shmat(mShmId, 0, 0);
|
||||
shmctl(mShmId, IPC_RMID, 0);
|
||||
if (data == (void *)-1)
|
||||
return false;
|
||||
mData = (unsigned char *)data;
|
||||
|
||||
mXShmImage = XShmCreateImage(mDisp, NULL,
|
||||
mDepth, ZPixmap,
|
||||
NULL, &mShmInfo,
|
||||
mSize.width,
|
||||
mSize.height);
|
||||
if (!mXShmImage)
|
||||
return false;
|
||||
mShmInfo.shmid = mShmId;
|
||||
|
||||
if (mStride != mXShmImage->bytes_per_line) {
|
||||
NS_WARNING("XStride and gfxSharedImageSurface calculated stride does not match");
|
||||
return false;
|
||||
}
|
||||
|
||||
mShmInfo.shmaddr = mXShmImage->data = (char*)data;
|
||||
mShmInfo.readOnly = False;
|
||||
if (!XShmAttach(mDisp, &mShmInfo))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxSharedImageSurface::ComputeFormat()
|
||||
{
|
||||
if (mDepth == 32)
|
||||
mFormat = ImageFormatARGB32;
|
||||
if (mDepth == 24)
|
||||
mFormat = ImageFormatRGB24;
|
||||
else {
|
||||
NS_WARNING("Unknown depth specified to gfxSharedImageSurface!");
|
||||
mFormat = ImageFormatUnknown;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxSharedImageSurface::ComputeDepth()
|
||||
{
|
||||
mDepth = 0;
|
||||
if (mFormat == ImageFormatARGB32)
|
||||
mDepth = 32;
|
||||
else if (mFormat == ImageFormatRGB24)
|
||||
mDepth = 24;
|
||||
else {
|
||||
NS_WARNING("Unknown format specified to gfxSharedImageSurface!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
long
|
||||
gfxSharedImageSurface::ComputeStride() const
|
||||
{
|
||||
long stride;
|
||||
|
||||
if (mDepth == 16)
|
||||
stride = mSize.width * 2;
|
||||
else if (mFormat == ImageFormatARGB32)
|
||||
stride = mSize.width * 4;
|
||||
else if (mFormat == ImageFormatRGB24)
|
||||
stride = mSize.width * 4;
|
||||
else if (mFormat == ImageFormatA8)
|
||||
stride = mSize.width;
|
||||
else if (mFormat == ImageFormatA1) {
|
||||
stride = (mSize.width + 7) / 8;
|
||||
} else {
|
||||
NS_WARNING("Unknown format specified to gfxImageSurface!");
|
||||
stride = mSize.width * 4;
|
||||
}
|
||||
|
||||
stride = ((stride + 3) / 4) * 4;
|
||||
|
||||
return stride;
|
||||
}
|
||||
|
||||
#endif /* HAVE_XSHM */
|
||||
#endif /* MOZ_X11 */
|
|
@ -257,7 +257,7 @@ EXTRA_DSO_LDOPTS += -ljprof
|
|||
endif
|
||||
|
||||
ifdef MOZ_ENABLE_QT
|
||||
EXTRA_DSO_LDOPTS += $(MOZ_QT_LDFLAGS)
|
||||
EXTRA_DSO_LDOPTS += $(MOZ_QT_LDFLAGS) $(XEXT_LIBS)
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -104,8 +104,8 @@ endif
|
|||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
CXXFLAGS += $(MOZ_QT_CFLAGS) $(GLIB_CFLAGS)
|
||||
CFLAGS += $(MOZ_QT_CFLAGS) $(GLIB_CFLAGS)
|
||||
CXXFLAGS += $(MOZ_QT_CFLAGS) $(GLIB_CFLAGS) $(MOZ_CAIRO_CFLAGS)
|
||||
CFLAGS += $(MOZ_QT_CFLAGS) $(GLIB_CFLAGS) $(MOZ_CAIRO_CFLAGS)
|
||||
|
||||
DEFINES += -D_IMPL_NS_WIDGET
|
||||
#DEFINES += -DDEBUG_WIDGETS
|
||||
|
|
|
@ -69,7 +69,11 @@
|
|||
|
||||
#include "gfxASurface.h"
|
||||
#include "gfxContext.h"
|
||||
#include "gfxQtPlatform.h"
|
||||
#include "gfxQPainterSurface.h"
|
||||
#ifdef MOZ_X11
|
||||
#include "gfxXlibSurface.h"
|
||||
#endif
|
||||
#include "nsIRenderingContext.h"
|
||||
|
||||
nsNativeThemeQt::nsNativeThemeQt()
|
||||
|
@ -93,6 +97,29 @@ static inline QRect qRectInPixels(const nsRect &aRect,
|
|||
NSAppUnitsToIntPixels(aRect.height, p2a));
|
||||
}
|
||||
|
||||
static inline QImage::Format
|
||||
_qimage_from_gfximage_format (gfxASurface::gfxImageFormat aFormat)
|
||||
{
|
||||
switch (aFormat) {
|
||||
case gfxASurface::ImageFormatARGB32:
|
||||
return QImage::Format_ARGB32_Premultiplied;
|
||||
case gfxASurface::ImageFormatRGB24:
|
||||
return QImage::Format_RGB32;
|
||||
case gfxASurface::ImageFormatA8:
|
||||
return QImage::Format_Indexed8;
|
||||
case gfxASurface::ImageFormatA1:
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
return QImage::Format_Mono;
|
||||
#else
|
||||
return QImage::Format_MonoLSB;
|
||||
#endif
|
||||
default:
|
||||
return QImage::Format_Invalid;
|
||||
}
|
||||
|
||||
return QImage::Format_Mono;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNativeThemeQt::DrawWidgetBackground(nsIRenderingContext* aContext,
|
||||
nsIFrame* aFrame,
|
||||
|
@ -103,19 +130,56 @@ nsNativeThemeQt::DrawWidgetBackground(nsIRenderingContext* aContext,
|
|||
gfxContext* context = aContext->ThebesContext();
|
||||
nsRefPtr<gfxASurface> surface = context->CurrentSurface();
|
||||
|
||||
if (surface->GetType() == gfxASurface::SurfaceTypeQPainter) {
|
||||
gfxQPainterSurface* qSurface = (gfxQPainterSurface*) (surface.get());
|
||||
QPainter *painter = qSurface->GetQPainter();
|
||||
NS_ASSERTION(painter, "Where'd my QPainter go?");
|
||||
if (!painter)
|
||||
return NS_ERROR_FAILURE;
|
||||
return DrawWidgetBackground(painter, aContext,
|
||||
aFrame, aWidgetType,
|
||||
aRect, aClipRect);
|
||||
}
|
||||
else if (surface->GetType() == gfxASurface::SurfaceTypeImage) {
|
||||
gfxImageSurface* qSurface = (gfxImageSurface*) (surface.get());
|
||||
QImage tempQImage(qSurface->Data(),
|
||||
qSurface->Width(),
|
||||
qSurface->Height(),
|
||||
qSurface->Stride(),
|
||||
_qimage_from_gfximage_format(qSurface->Format()));
|
||||
QPainter painter(&tempQImage);
|
||||
return DrawWidgetBackground(&painter, aContext,
|
||||
aFrame, aWidgetType,
|
||||
aRect, aClipRect);
|
||||
}
|
||||
#ifdef MOZ_X11
|
||||
else if (surface->GetType() == gfxASurface::SurfaceTypeXlib) {
|
||||
gfxXlibSurface* qSurface = (gfxXlibSurface*) (surface.get());
|
||||
QPixmap pixmap(QPixmap::fromX11Pixmap(qSurface->XDrawable()));
|
||||
QPainter painter(&pixmap);
|
||||
return DrawWidgetBackground(&painter, aContext,
|
||||
aFrame, aWidgetType,
|
||||
aRect, aClipRect);
|
||||
}
|
||||
#endif
|
||||
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNativeThemeQt::DrawWidgetBackground(QPainter *qPainter,
|
||||
nsIRenderingContext* aContext,
|
||||
nsIFrame* aFrame,
|
||||
PRUint8 aWidgetType,
|
||||
const nsRect& aRect,
|
||||
const nsRect& aClipRect)
|
||||
|
||||
{
|
||||
gfxContext* context = aContext->ThebesContext();
|
||||
nsRefPtr<gfxASurface> surface = context->CurrentSurface();
|
||||
|
||||
context->UpdateSurfaceClip();
|
||||
|
||||
if (surface->GetType() != gfxASurface::SurfaceTypeQPainter)
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
gfxQPainterSurface* qSurface = (gfxQPainterSurface*) (surface.get());
|
||||
QPainter* qPainter = qSurface->GetQPainter();
|
||||
|
||||
NS_ASSERTION(qPainter, "Where'd my QPainter go?");
|
||||
|
||||
if (qPainter == nsnull)
|
||||
return NS_OK;
|
||||
|
||||
QStyle* style = qApp->style();
|
||||
|
||||
qPainter->save();
|
||||
|
|
|
@ -106,6 +106,13 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
inline nsresult DrawWidgetBackground(QPainter *qPainter,
|
||||
nsIRenderingContext* aContext,
|
||||
nsIFrame* aFrame,
|
||||
PRUint8 aWidgetType,
|
||||
const nsRect& aRect,
|
||||
const nsRect& aClipRect);
|
||||
|
||||
inline PRInt32 GetAppUnitsPerDevPixel(nsIRenderingContext* aContext){
|
||||
nsCOMPtr<nsIDeviceContext> dctx = nsnull;
|
||||
aContext->GetDeviceContext(*getter_AddRefs(dctx));
|
||||
|
|
|
@ -89,7 +89,19 @@
|
|||
#include "gfxXlibSurface.h"
|
||||
#include "gfxQPainterSurface.h"
|
||||
#include "gfxContext.h"
|
||||
#include "gfxSharedImageSurface.h"
|
||||
|
||||
// Buffered Pixmap stuff
|
||||
static QPixmap *gBufferPixmap = nsnull;
|
||||
static int gBufferPixmapUsageCount = 0;
|
||||
|
||||
// Buffered shared image + pixmap
|
||||
static gfxSharedImageSurface *gBufferImage = nsnull;
|
||||
static gfxSharedImageSurface *gBufferImageTemp = nsnull;
|
||||
PRBool gNeedColorConversion = PR_FALSE;
|
||||
extern "C" {
|
||||
#include "pixman.h"
|
||||
}
|
||||
|
||||
/* For PrepareNativeWidget */
|
||||
static NS_DEFINE_IID(kDeviceContextCID, NS_DEVICE_CONTEXT_CID);
|
||||
|
@ -175,6 +187,90 @@ nsWindow::nsWindow()
|
|||
mIsTransparent = PR_FALSE;
|
||||
|
||||
mCursor = eCursor_standard;
|
||||
|
||||
gBufferPixmapUsageCount++;
|
||||
}
|
||||
|
||||
static inline gfxASurface::gfxImageFormat
|
||||
_depth_to_gfximage_format(PRInt32 aDepth)
|
||||
{
|
||||
switch (aDepth) {
|
||||
case 32:
|
||||
return gfxASurface::ImageFormatARGB32;
|
||||
case 24:
|
||||
return gfxASurface::ImageFormatRGB24;
|
||||
default:
|
||||
return gfxASurface::ImageFormatUnknown;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
FreeOffScreenBuffers(void)
|
||||
{
|
||||
delete gBufferImage;
|
||||
delete gBufferImageTemp;
|
||||
delete gBufferPixmap;
|
||||
gBufferImage = nsnull;
|
||||
gBufferImageTemp = nsnull;
|
||||
gBufferPixmap = nsnull;
|
||||
}
|
||||
|
||||
static bool
|
||||
UpdateOffScreenBuffers(QSize aSize, int aDepth)
|
||||
{
|
||||
gfxIntSize size(aSize.width(), aSize.height());
|
||||
if (gBufferPixmap) {
|
||||
if (gBufferPixmap->size().width() < size.width ||
|
||||
gBufferPixmap->size().height() < size.height) {
|
||||
FreeOffScreenBuffers();
|
||||
} else
|
||||
return true;
|
||||
}
|
||||
|
||||
gBufferPixmap = new QPixmap(size.width, size.height);
|
||||
if (!gBufferPixmap)
|
||||
return false;
|
||||
|
||||
if (gfxQtPlatform::GetPlatform()->GetRenderMode() == gfxQtPlatform::RENDER_XLIB)
|
||||
return true;
|
||||
|
||||
// Check if system depth has related gfxImage format
|
||||
gfxASurface::gfxImageFormat format =
|
||||
_depth_to_gfximage_format(gBufferPixmap->x11Info().depth());
|
||||
|
||||
gNeedColorConversion = (format == gfxASurface::ImageFormatUnknown);
|
||||
|
||||
gBufferImage = new gfxSharedImageSurface();
|
||||
if (!gBufferImage) {
|
||||
FreeOffScreenBuffers();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!gBufferImage->Init(gfxIntSize(gBufferPixmap->size().width(),
|
||||
gBufferPixmap->size().height()),
|
||||
_depth_to_gfximage_format(gBufferPixmap->x11Info().depth()))) {
|
||||
FreeOffScreenBuffers();
|
||||
return false;
|
||||
}
|
||||
|
||||
// gfxImageSurface does not support system color depth format
|
||||
// we have to paint it with temp surface and color conversion
|
||||
if (!gNeedColorConversion)
|
||||
return true;
|
||||
|
||||
gBufferImageTemp = new gfxSharedImageSurface();
|
||||
if (!gBufferImageTemp) {
|
||||
FreeOffScreenBuffers();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!gBufferImageTemp->Init(gfxIntSize(gBufferPixmap->size().width(),
|
||||
gBufferPixmap->size().height()),
|
||||
gfxASurface::ImageFormatRGB24)) {
|
||||
FreeOffScreenBuffers();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
nsWindow::~nsWindow()
|
||||
|
@ -221,6 +317,12 @@ nsWindow::Destroy(void)
|
|||
LOG(("nsWindow::Destroy [%p]\n", (void *)this));
|
||||
mIsDestroyed = PR_TRUE;
|
||||
|
||||
if (gBufferPixmapUsageCount &&
|
||||
--gBufferPixmapUsageCount == 0) {
|
||||
|
||||
FreeOffScreenBuffers();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWidget> rollupWidget = do_QueryReferent(gRollupWindow);
|
||||
if (static_cast<nsIWidget *>(this) == rollupWidget.get()) {
|
||||
if (gRollupListener)
|
||||
|
@ -830,6 +932,20 @@ nsWindow::GetAttention(PRInt32 aCycleCount)
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
#ifdef MOZ_X11
|
||||
static already_AddRefed<gfxASurface>
|
||||
GetSurfaceForQWidget(QPixmap* aDrawable)
|
||||
{
|
||||
gfxASurface* result =
|
||||
new gfxXlibSurface(aDrawable->x11Info().display(),
|
||||
aDrawable->handle(),
|
||||
(Visual*)aDrawable->x11Info().visual(),
|
||||
gfxIntSize(aDrawable->size().width(), aDrawable->size().height()));
|
||||
NS_IF_ADDREF(result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsEventStatus
|
||||
nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption)
|
||||
{
|
||||
|
@ -857,7 +973,25 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption)
|
|||
|
||||
updateRegion->SetTo( (int)r.x(), (int)r.y(), (int)r.width(), (int)r.height() );
|
||||
|
||||
nsRefPtr<gfxASurface> targetSurface = new gfxQPainterSurface(aPainter);
|
||||
gfxQtPlatform::RenderMode renderMode = gfxQtPlatform::GetPlatform()->GetRenderMode();
|
||||
// Prepare offscreen buffers if RenderMode Xlib or Image
|
||||
if (renderMode != gfxQtPlatform::RENDER_QPAINTER)
|
||||
if (!UpdateOffScreenBuffers(r.size().toSize(), QX11Info().depth()))
|
||||
return nsEventStatus_eIgnore;
|
||||
|
||||
nsRefPtr<gfxASurface> targetSurface = nsnull;
|
||||
if (renderMode == gfxQtPlatform::RENDER_XLIB) {
|
||||
targetSurface = GetSurfaceForQWidget(gBufferPixmap);
|
||||
} else if (renderMode == gfxQtPlatform::RENDER_SHARED_IMAGE) {
|
||||
targetSurface = gNeedColorConversion ? gBufferImageTemp->getASurface()
|
||||
: gBufferImage->getASurface();
|
||||
} else if (renderMode == gfxQtPlatform::RENDER_QPAINTER) {
|
||||
targetSurface = new gfxQPainterSurface(aPainter);
|
||||
}
|
||||
|
||||
if (NS_UNLIKELY(!targetSurface))
|
||||
return nsEventStatus_eIgnore;
|
||||
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface);
|
||||
|
||||
nsCOMPtr<nsIRenderingContext> rc;
|
||||
|
@ -888,6 +1022,46 @@ nsWindow::DoPaint(QPainter* aPainter, const QStyleOptionGraphicsItem* aOption)
|
|||
|
||||
LOGDRAW(("[%p] draw done\n", this));
|
||||
|
||||
if (renderMode == gfxQtPlatform::RENDER_SHARED_IMAGE) {
|
||||
if (gNeedColorConversion) {
|
||||
pixman_image_t *src_image = NULL;
|
||||
pixman_image_t *dst_image = NULL;
|
||||
src_image = pixman_image_create_bits(PIXMAN_x8r8g8b8,
|
||||
gBufferImageTemp->GetSize().width,
|
||||
gBufferImageTemp->GetSize().height,
|
||||
(uint32_t*)gBufferImageTemp->Data(),
|
||||
gBufferImageTemp->Stride());
|
||||
dst_image = pixman_image_create_bits(PIXMAN_r5g6b5,
|
||||
gBufferImage->GetSize().width,
|
||||
gBufferImage->GetSize().height,
|
||||
(uint32_t*)gBufferImage->Data(),
|
||||
gBufferImage->Stride());
|
||||
pixman_image_composite(PIXMAN_OP_SRC,
|
||||
src_image,
|
||||
NULL,
|
||||
dst_image,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
gBufferImageTemp->GetSize().width,
|
||||
gBufferImageTemp->GetSize().height);
|
||||
pixman_image_unref(src_image);
|
||||
pixman_image_unref(dst_image);
|
||||
}
|
||||
|
||||
Display *disp = gBufferPixmap->x11Info().display();
|
||||
XGCValues gcv;
|
||||
gcv.graphics_exposures = False;
|
||||
GC gc = XCreateGC (disp, gBufferPixmap->handle(), GCGraphicsExposures, &gcv);
|
||||
XShmPutImage(disp, gBufferPixmap->handle(), gc, gBufferImage->image(),
|
||||
0, 0, 0, 0, gBufferImage->GetSize().width, gBufferImage->GetSize().height,
|
||||
False);
|
||||
XFreeGC (disp, gc);
|
||||
}
|
||||
|
||||
if (renderMode != gfxQtPlatform::RENDER_QPAINTER)
|
||||
aPainter->drawPixmap(QPoint(0, 0), *gBufferPixmap);
|
||||
|
||||
ctx = nsnull;
|
||||
targetSurface = nsnull;
|
||||
|
||||
|
@ -1804,8 +1978,21 @@ nsWindow::GetThebesSurface()
|
|||
/* This is really a dummy surface; this is only used when doing reflow, because
|
||||
* we need a RenderingContext to measure text against.
|
||||
*/
|
||||
if (!mThebesSurface)
|
||||
mThebesSurface = new gfxQPainterSurface(gfxIntSize(5,5), gfxASurface::CONTENT_COLOR);
|
||||
if (mThebesSurface)
|
||||
return mThebesSurface;
|
||||
|
||||
gfxQtPlatform::RenderMode renderMode = gfxQtPlatform::GetPlatform()->GetRenderMode();
|
||||
if (renderMode == gfxQtPlatform::RENDER_QPAINTER) {
|
||||
mThebesSurface = new gfxQPainterSurface(gfxIntSize(1, 1), gfxASurface::CONTENT_COLOR);
|
||||
} else if (renderMode == gfxQtPlatform::RENDER_XLIB) {
|
||||
mThebesSurface = new gfxXlibSurface(QX11Info().display(),
|
||||
(Visual*)QX11Info().visual(),
|
||||
gfxIntSize(1, 1), QX11Info().depth());
|
||||
}
|
||||
if (!mThebesSurface) {
|
||||
gfxASurface::gfxImageFormat imageFormat = gfxASurface::ImageFormatRGB24;
|
||||
mThebesSurface = new gfxImageSurface(gfxIntSize(1, 1), imageFormat);
|
||||
}
|
||||
|
||||
return mThebesSurface;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче