Bug 395983 - "Duplicated Flash menus using r60(+) of Flash player" (do native drawing instead) [p=kinetik@flim.org (Matthew Gregan) r=vlad sr=roc a=blocking1.9+]

This commit is contained in:
reed@reedloden.com 2008-02-20 03:33:27 -08:00
Родитель 4ef483fb52
Коммит a192027417
7 изменённых файлов: 261 добавлений и 65 удалений

Просмотреть файл

@ -81,6 +81,7 @@ EXPORTS += gfxPlatformMac.h \
gfxQuartzImageSurface.h \
gfxQuartzPDFSurface.h \
gfxAtsuiFonts.h \
gfxQuartzNativeDrawing.h \
$(NULL)
ifdef MOZ_ENABLE_GLITZ

Просмотреть файл

@ -0,0 +1,85 @@
/* -*- 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 Thebes gfx.
*
* The Initial Developer of the Original Code is Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Matthew Gregan <kinetik@flim.org>
*
* 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 _GFXQUARTZNATIVEDRAWING_H_
#define _GFXQUARTZNATIVEDRAWING_H_
#include "gfxContext.h"
#include "gfxQuartzSurface.h"
class THEBES_API gfxQuartzNativeDrawing {
public:
/* Create native Quartz drawing for a rectangle bounded by
* nativeRect.
*
* Typical usage looks like:
*
* gfxQuartzNativeDrawing nativeDraw(ctx, nativeRect);
* CGContextRef cgContext = nativeDraw.BeginNativeDrawing();
* if (!cgContext)
* return NS_ERROR_FAILURE;
*
* ... call Quartz operations on CGContextRef to draw to nativeRect ...
*
* nativeDraw.EndNativeDrawing();
*/
gfxQuartzNativeDrawing(gfxContext *ctx,
const gfxRect& nativeRect);
/* Returns a CGContextRef which may be used for native drawing. This
* CGContextRef is valid until EndNativeDrawing is called; if it is used
* for drawing after that time, the result is undefined. */
CGContextRef BeginNativeDrawing();
/* Marks the end of native drawing */
void EndNativeDrawing();
private:
// don't allow copying via construction or assignment
gfxQuartzNativeDrawing(const gfxQuartzNativeDrawing&);
const gfxQuartzNativeDrawing& operator=(const gfxQuartzNativeDrawing&);
nsRefPtr<gfxContext> mContext;
gfxRect mNativeRect; // not yet used, will be needed for offscreen buffers
// saved state
nsRefPtr<gfxQuartzSurface> mQuartzSurface;
CGContextRef mCGContext;
};
#endif

Просмотреть файл

@ -109,6 +109,7 @@ CPPSRCS += \
$(NULL)
#CPPSRCS += gfxPDFSurface.cpp
CPPSRCS += nsUnicodeRange.cpp
CPPSRCS += gfxQuartzNativeDrawing.cpp
CMMSRCS = gfxQuartzFontCache.mm

Просмотреть файл

@ -0,0 +1,131 @@
/* -*- 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 Thebes gfx.
*
* The Initial Developer of the Original Code is Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Matthew Gregan <kinetik@flim.org>
*
* 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 "nsMathUtils.h"
#include "gfxQuartzNativeDrawing.h"
#include "gfxQuartzSurface.h"
// see cairo-quartz-surface.c for the complete list of these
enum {
kPrivateCGCompositeSourceOver = 2
};
// private Quartz routine needed here
extern "C" {
CG_EXTERN void CGContextSetCompositeOperation(CGContextRef, int);
}
gfxQuartzNativeDrawing::gfxQuartzNativeDrawing(gfxContext* ctx,
const gfxRect& nativeRect)
: mContext(ctx), mNativeRect(nativeRect)
{
}
CGContextRef
gfxQuartzNativeDrawing::BeginNativeDrawing()
{
NS_ASSERTION(!mQuartzSurface, "BeginNativeDrawing called when drawing already in progress");
gfxPoint deviceOffset;
nsRefPtr<gfxASurface> surf = mContext->CurrentSurface(&deviceOffset.x, &deviceOffset.y);
if (!surf || surf->CairoStatus())
return nsnull;
// if this is a native Quartz surface, we don't have to redirect
// rendering to our own CGContextRef; in most cases, we are able to
// use the CGContextRef from the surface directly. we can extend
// this to support offscreen drawing fairly easily in the future.
if (surf->GetType() == gfxASurface::SurfaceTypeQuartz &&
(surf->GetContentType() == gfxASurface::CONTENT_COLOR ||
(surf->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA))) {
mQuartzSurface = static_cast<gfxQuartzSurface*>(static_cast<gfxASurface*>(surf.get()));
} else {
// XXXkinetik we could create and use a temp surface here and draw
// it back to the gfxContext in EndNativeDrawing like the Windows
// version of this class
NS_WARNING("unhandled surface type");
return nsnull;
}
// Need to force the clip to be set
mContext->UpdateSurfaceClip();
// grab the CGContextRef
mCGContext = mQuartzSurface->GetCGContext();
if (!mCGContext)
return nsnull;
gfxMatrix m = mContext->CurrentMatrix();
CGContextSaveGState(mCGContext);
CGContextTranslateCTM(mCGContext, deviceOffset.x, deviceOffset.y);
// I -think- that this context will always have an identity
// transform (since we don't maintain a transform on it in
// cairo-land, and instead push/pop as needed)
gfxFloat x0 = m.x0;
gfxFloat y0 = m.y0;
// We round x0/y0 if we don't have a scale, because otherwise things get
// rendered badly
// XXX how should we be rounding x0/y0?
if (!m.HasNonTranslationOrFlip()) {
x0 = floor(x0 + 0.5);
y0 = floor(y0 + 0.5);
}
CGContextConcatCTM(mCGContext, CGAffineTransformMake(m.xx, m.yx,
m.xy, m.yy,
x0, y0));
// bug 382049 - need to explicity set the composite operation to sourceOver
CGContextSetCompositeOperation(mCGContext, kPrivateCGCompositeSourceOver);
return mCGContext;
}
void
gfxQuartzNativeDrawing::EndNativeDrawing()
{
NS_ASSERTION(mQuartzSurface, "EndNativeDrawing called without BeginNativeDrawing");
// we drew directly to a shared CGContextRef; restore previous context state
CGContextRestoreGState(mCGContext);
mQuartzSurface->MarkDirty();
mQuartzSurface = nsnull;
}

Просмотреть файл

@ -145,6 +145,10 @@
#include "nsContentCID.h"
static NS_DEFINE_CID(kRangeCID, NS_RANGE_CID);
#ifdef XP_MACOSX
#include "gfxQuartzNativeDrawing.h"
#endif
#ifdef MOZ_X11
#include <X11/Xlib.h>
/* X headers suck */
@ -1250,8 +1254,35 @@ nsObjectFrame::PaintPlugin(nsIRenderingContext& aRenderingContext,
// Screen painting code
#if defined(XP_MACOSX)
// delegate all painting to the plugin instance.
if (mInstanceOwner)
if (mInstanceOwner) {
if (mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreGraphics) {
PRInt32 p2a = PresContext()->AppUnitsPerDevPixel();
gfxRect nativeClipRect(aDirtyRect.x, aDirtyRect.y,
aDirtyRect.width, aDirtyRect.height);
nativeClipRect.ScaleInverse(gfxFloat(p2a));
gfxContext* ctx = aRenderingContext.ThebesContext();
gfxQuartzNativeDrawing nativeDrawing(ctx, nativeClipRect);
CGContextRef cgContext = nativeDrawing.BeginNativeDrawing();
if (!cgContext) {
NS_WARNING("null CGContextRef during PaintPlugin");
return;
}
// XXXkinetik if gfxQuartzNativeDrawing ever gave us a CGContext other
// than the current one, we would need to pass that to the plugin via
// SetWindow, just assert that they're the same for now
nsPluginPort* pluginPort = mInstanceOwner->GetPluginPort();
NS_ASSERTION(pluginPort->cgPort.context == cgContext,
"BeginNativeDrawing using different CGContextRef to plugin");
mInstanceOwner->Paint(aDirtyRect);
nativeDrawing.EndNativeDrawing();
} else {
mInstanceOwner->Paint(aDirtyRect);
}
}
#elif defined(MOZ_X11)
if (mInstanceOwner)
{

Просмотреть файл

@ -649,10 +649,7 @@ void* nsChildView::GetNativeData(PRUint32 aDataType)
if ([mView isKindOfClass:[ChildView class]])
[(ChildView*)mView setIsPluginView:YES];
if ([NSView focusView] == mView)
mPluginPort.cgPort.context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
else
mPluginPort.cgPort.context = NULL;
mPluginPort.cgPort.context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
NSWindow* window = [mView nativeWindow];
if (window) {

Просмотреть файл

@ -23,6 +23,7 @@
* Vladimir Vukicevic <vladimir@pobox.com> (HITheme rewrite)
* Josh Aas <josh@mozilla.com>
* Colin Barrett <cbarrett@mozilla.com>
* Matthew Gregan <kinetik@flim.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -58,19 +59,14 @@
#include "gfxContext.h"
#include "gfxQuartzSurface.h"
#include "gfxQuartzNativeDrawing.h"
#define DRAW_IN_FRAME_DEBUG 0
#define SCROLLBARS_VISUAL_DEBUG 0
// see cairo-quartz-surface.c for the complete list of these
enum {
kPrivateCGCompositeSourceOver = 2
};
// private Quartz routines needed here
extern "C" {
CG_EXTERN void CGContextSetCTM(CGContextRef, CGAffineTransform);
CG_EXTERN void CGContextSetCompositeOperation (CGContextRef, int);
}
// Copied from nsLookAndFeel.h
@ -844,30 +840,18 @@ nsNativeThemeCocoa::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame
aContext->GetDeviceContext(*getter_AddRefs(dctx));
PRInt32 p2a = dctx->AppUnitsPerDevPixel();
gfxRect nativeClipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height);
gfxRect nativeWidgetRect(aRect.x, aRect.y, aRect.width, aRect.height);
nativeWidgetRect.ScaleInverse(gfxFloat(p2a));
nativeClipRect.ScaleInverse(gfxFloat(p2a));
nsRefPtr<gfxContext> thebesCtx = aContext->ThebesContext();
if (!thebesCtx)
return NS_ERROR_FAILURE;
thebesCtx->UpdateSurfaceClip();
double offsetX = 0.0, offsetY = 0.0;
nsRefPtr<gfxASurface> thebesSurface = thebesCtx->CurrentSurface(&offsetX, &offsetY);
if (thebesSurface->CairoStatus() != 0) {
NS_WARNING("Got Cairo surface with nonzero error status");
return NS_ERROR_FAILURE;
}
if (thebesSurface->GetType() != gfxASurface::SurfaceTypeQuartz) {
NS_WARNING("Expected surface of type Quartz, got something else");
return NS_ERROR_FAILURE;
}
gfxMatrix mat = thebesCtx->CurrentMatrix();
gfxQuartzSurface* quartzSurf = (gfxQuartzSurface*) (thebesSurface.get());
CGContextRef cgContext = quartzSurf->GetCGContext();
//fprintf (stderr, "surface: %p cgContext: %p\n", quartzSurf, cgContext);
gfxQuartzNativeDrawing nativeDrawing(thebesCtx, nativeClipRect);
CGContextRef cgContext = nativeDrawing.BeginNativeDrawing();
if (cgContext == nsnull) {
// The Quartz surface handles 0x0 surfaces by internally
// making all operations no-ops; there's no cgcontext created for them.
@ -876,37 +860,6 @@ nsNativeThemeCocoa::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame
return NS_OK;
}
// Eventually we can just do a GetCTM and restore it with SetCTM,
// but for now do a full save/restore
CGAffineTransform mm0 = CGContextGetCTM(cgContext);
CGContextSaveGState(cgContext);
//CGContextSetCTM(cgContext, CGAffineTransformIdentity);
// Apply any origin offset we have first, so it gets picked up by any other
// transforms we have.
CGContextTranslateCTM(cgContext, offsetX, offsetY);
// I -think- that this context will always have an identity
// transform (since we don't maintain a transform on it in
// cairo-land, and instead push/pop as needed)
if (mat.HasNonTranslationOrFlip()) {
// If we have a scale, I think we've already lost; so don't round
// anything here
CGContextConcatCTM(cgContext,
CGAffineTransformMake(mat.xx, mat.yx,
mat.xy, mat.yy,
mat.x0, mat.y0));
} else {
// Otherwise, we round the x0/y0, because otherwise things get rendered badly
// XXX how should we be rounding the x0/y0?
CGContextConcatCTM(cgContext,
CGAffineTransformMake(mat.xx, mat.yx,
mat.xy, mat.yy,
floor(mat.x0 + 0.5),
floor(mat.y0 + 0.5)));
}
#if 0
if (1 /*aWidgetType == NS_THEME_TEXTFIELD*/) {
fprintf(stderr, "Native theme drawing widget %d [%p] dis:%d in rect [%d %d %d %d]\n",
@ -926,9 +879,6 @@ nsNativeThemeCocoa::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame
NSAppUnitsToIntPixels(aRect.width, p2a),
NSAppUnitsToIntPixels(aRect.height, p2a));
// 382049 - need to explicitly set the composite operation to sourceOver
CGContextSetCompositeOperation(cgContext, kPrivateCGCompositeSourceOver);
#if 0
fprintf(stderr, " --> macRect %f %f %f %f\n",
macRect.origin.x, macRect.origin.y, macRect.size.width, macRect.size.height);
@ -1230,7 +1180,7 @@ nsNativeThemeCocoa::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame
break;
}
CGContextRestoreGState(cgContext);
nativeDrawing.EndNativeDrawing();
return NS_OK;
}