| /* |
| * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| |
| #include "config.h" |
| #import "KCanvasPathQuartz.h" |
| #import "KRenderingDeviceQuartz.h" |
| #import "KCanvasMaskerQuartz.h" |
| #import "KCanvasResourcesQuartz.h" |
| #import "KCanvasFilterQuartz.h" |
| #import "KRenderingPaintServerQuartz.h" |
| #import "QuartzSupport.h" |
| |
| #import "kcanvas/KCanvas.h" |
| #import "KCanvasMatrix.h" |
| #import "KCanvasItemQuartz.h" |
| #import "KRenderingFillPainter.h" |
| #import "KRenderingStrokePainter.h" |
| |
| #import <AppKit/NSGraphicsContext.h> |
| |
| #import "KWQLogging.h" |
| |
| KRenderingDeviceContextQuartz::KRenderingDeviceContextQuartz(CGContextRef context) : m_cgContext(CGContextRetain(context)), m_nsGraphicsContext(0) |
| { |
| ASSERT(m_cgContext); |
| } |
| |
| KRenderingDeviceContextQuartz::~KRenderingDeviceContextQuartz() |
| { |
| CGContextRelease(m_cgContext); |
| [m_nsGraphicsContext release]; |
| } |
| |
| KCanvasMatrix KRenderingDeviceContextQuartz::concatCTM(const KCanvasMatrix &worldMatrix) |
| { |
| KCanvasMatrix ret = ctm(); |
| CGAffineTransform wMatrix = CGAffineTransformMake(worldMatrix.a(), worldMatrix.b(), worldMatrix.c(), |
| worldMatrix.d(), worldMatrix.e(), worldMatrix.f()); |
| CGContextConcatCTM(m_cgContext, wMatrix); |
| return ret; |
| } |
| |
| KCanvasMatrix KRenderingDeviceContextQuartz::ctm() const |
| { |
| CGAffineTransform contextCTM = CGContextGetCTM(m_cgContext); |
| return KCanvasMatrix(contextCTM.a, contextCTM.b, contextCTM.c, contextCTM.d, contextCTM.tx, contextCTM.ty); |
| } |
| |
| QRect KRenderingDeviceContextQuartz::mapFromVisual(const QRect &rect) |
| { |
| return QRect(); |
| } |
| |
| QRect KRenderingDeviceContextQuartz::mapToVisual(const QRect &rect) |
| { |
| return QRect(); |
| } |
| |
| NSGraphicsContext *KRenderingDeviceContextQuartz::nsGraphicsContext() |
| { |
| if (!m_nsGraphicsContext && m_cgContext) |
| m_nsGraphicsContext = [[NSGraphicsContext graphicsContextWithGraphicsPort:m_cgContext flipped:NO] retain]; |
| return m_nsGraphicsContext; |
| } |
| |
| static bool __useFilters = true; |
| |
| bool KRenderingDeviceQuartz::filtersEnabled() |
| { |
| return __useFilters; |
| } |
| |
| void KRenderingDeviceQuartz::setFiltersEnabled(bool enabled) |
| { |
| __useFilters = enabled; |
| } |
| |
| static bool __useHardwareRendering = true; |
| |
| bool KRenderingDeviceQuartz::hardwareRenderingEnabled() |
| { |
| return __useHardwareRendering; |
| } |
| |
| void KRenderingDeviceQuartz::setHardwareRenderingEnabled(bool enabled) |
| { |
| __useHardwareRendering = enabled; |
| } |
| |
| #pragma mark - |
| #pragma mark Context Management |
| |
| KRenderingDeviceContextQuartz *KRenderingDeviceQuartz::quartzContext() const |
| { |
| return static_cast<KRenderingDeviceContextQuartz *>(currentContext()); |
| } |
| |
| CGContextRef KRenderingDeviceQuartz::currentCGContext() const |
| { |
| ASSERT(quartzContext()); |
| return quartzContext()->cgContext(); |
| } |
| |
| void KRenderingDeviceQuartz::pushContext(KRenderingDeviceContext *context) |
| { |
| ASSERT(context); |
| KRenderingDevice::pushContext(context); |
| [NSGraphicsContext saveGraphicsState]; |
| [NSGraphicsContext setCurrentContext:quartzContext()->nsGraphicsContext()]; |
| ASSERT(quartzContext()->nsGraphicsContext() == [NSGraphicsContext currentContext]); |
| ASSERT(currentCGContext() == QPainter().currentContext()); |
| } |
| |
| KRenderingDeviceContext *KRenderingDeviceQuartz::popContext() |
| { |
| [NSGraphicsContext restoreGraphicsState]; |
| KRenderingDeviceContext *poppedContext = KRenderingDevice::popContext(); |
| ASSERT(!currentContext() || (currentCGContext() == QPainter().currentContext())); |
| return poppedContext; |
| } |
| |
| KRenderingDeviceContext *KRenderingDeviceQuartz::contextForImage(KCanvasImage *image) const |
| { |
| KCanvasImageQuartz *quartzImage = static_cast<KCanvasImageQuartz *>(image); |
| CGLayerRef cgLayer = quartzImage->cgLayer(); |
| if (!cgLayer) { |
| // FIXME: we might not get back a layer if this is a loaded image |
| // maybe this logic should go into KCanvasImage? |
| cgLayer = CGLayerCreateWithContext(currentCGContext(), CGSize(image->size() + QSize(1,1)), NULL); // FIXME + 1 is a hack |
| // FIXME: we should composite the original image onto the layer... |
| quartzImage->setCGLayer(cgLayer); |
| CGLayerRelease(cgLayer); |
| } |
| return new KRenderingDeviceContextQuartz(CGLayerGetContext(cgLayer)); |
| } |
| |
| #pragma mark - |
| #pragma mark Path Management |
| |
| KCanvasPath* KRenderingDeviceQuartz::createPath() const |
| { |
| return new KCanvasPathQuartz(); |
| } |
| |
| QString KRenderingDeviceQuartz::stringForPath(const KCanvasPath *path) |
| { |
| QString result; |
| if (path) { |
| CGPathRef cgPath = static_cast<const KCanvasPathQuartz *>(path)->cgPath(); |
| CFStringRef pathString = CFStringFromCGPath(cgPath); |
| result = QString::fromCFString(pathString); |
| CFRelease(pathString); |
| } |
| return result; |
| } |
| |
| #pragma mark - |
| #pragma mark Resource Creation |
| |
| KRenderingPaintServer *KRenderingDeviceQuartz::createPaintServer(const KCPaintServerType &type) const |
| { |
| KRenderingPaintServer *newServer = NULL; |
| switch(type) |
| { |
| case PS_SOLID: newServer = new KRenderingPaintServerSolidQuartz(); break; |
| case PS_PATTERN: newServer = new KRenderingPaintServerPatternQuartz(); break; |
| case PS_IMAGE: newServer = new KRenderingPaintServerImageQuartz(); break; |
| case PS_LINEAR_GRADIENT: newServer = new KRenderingPaintServerLinearGradientQuartz(); break; |
| case PS_RADIAL_GRADIENT: newServer = new KRenderingPaintServerRadialGradientQuartz(); break; |
| } |
| return newServer; |
| } |
| |
| KCanvasContainer *KRenderingDeviceQuartz::createContainer(RenderArena *arena, khtml::RenderStyle *style, KSVG::SVGStyledElementImpl *node) const |
| { |
| return new (arena) KCanvasContainerQuartz(node); |
| } |
| |
| RenderPath *KRenderingDeviceQuartz::createItem(RenderArena *arena, khtml::RenderStyle *style, KSVG::SVGStyledElementImpl *node, KCanvasPath* path) const |
| { |
| RenderPath *item = new (arena) KCanvasItemQuartz(style, node); |
| item->changePath(path); |
| return item; |
| } |
| |
| KCanvasResource *KRenderingDeviceQuartz::createResource(const KCResourceType &type) const |
| { |
| switch (type) { |
| case RS_CLIPPER: |
| return new KCanvasClipperQuartz(); |
| case RS_MARKER: |
| return new KCanvasMarker(); |
| case RS_IMAGE: |
| return new KCanvasImageQuartz(); |
| case RS_FILTER: |
| return new KCanvasFilterQuartz(); |
| case RS_MASKER: |
| return new KCanvasMaskerQuartz(); |
| } |
| ERROR("Failed to create resource of type: %i", type); |
| return 0; |
| } |
| |
| KCanvasFilterEffect *KRenderingDeviceQuartz::createFilterEffect(const KCFilterEffectType &type) const |
| { |
| switch(type) |
| { |
| /* Light sources are contained by the diffuse/specular light blocks |
| case FE_DISTANT_LIGHT: |
| case FE_POINT_LIGHT: |
| case FE_SPOT_LIGHT: |
| */ |
| case FE_BLEND: return new KCanvasFEBlendQuartz(); |
| case FE_COLOR_MATRIX: return new KCanvasFEColorMatrixQuartz(); |
| // case FE_COMPONENT_TRANSFER: |
| case FE_COMPOSITE: return new KCanvasFECompositeQuartz(); |
| // case FE_CONVOLVE_MATRIX: |
| case FE_DIFFUSE_LIGHTING: return new KCanvasFEDiffuseLightingQuartz(); |
| // case FE_DISPLACEMENT_MAP: |
| case FE_FLOOD: return new KCanvasFEFloodQuartz(); |
| case FE_GAUSSIAN_BLUR: return new KCanvasFEGaussianBlurQuartz(); |
| case FE_IMAGE: return new KCanvasFEImageQuartz(); |
| case FE_MERGE: return new KCanvasFEMergeQuartz(); |
| // case FE_MORPHOLOGY: |
| case FE_OFFSET: return new KCanvasFEOffsetQuartz(); |
| case FE_SPECULAR_LIGHTING: return new KCanvasFESpecularLightingQuartz(); |
| case FE_TILE: return new KCanvasFETileQuartz(); |
| // case FE_TURBULENCE: |
| default: |
| return 0; |
| } |
| } |
| |