4632N/A/*
4632N/A * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
4632N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4632N/A *
4632N/A * This code is free software; you can redistribute it and/or modify it
4632N/A * under the terms of the GNU General Public License version 2 only, as
4632N/A * published by the Free Software Foundation. Oracle designates this
4632N/A * particular file as subject to the "Classpath" exception as provided
4632N/A * by Oracle in the LICENSE file that accompanied this code.
4632N/A *
4632N/A * This code is distributed in the hope that it will be useful, but WITHOUT
4632N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
4632N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
4632N/A * version 2 for more details (a copy is included in the LICENSE file that
4632N/A * accompanied this code).
4632N/A *
4632N/A * You should have received a copy of the GNU General Public License version
4632N/A * 2 along with this work; if not, write to the Free Software Foundation,
4632N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
4632N/A *
4632N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
4632N/A * or visit www.oracle.com if you need additional information or have any
4632N/A * questions.
4632N/A */
4632N/A
4632N/A#import "java_awt_image_BufferedImage.h"
4632N/A#import "java_awt_geom_PathIterator.h"
4632N/A#import "sun_java2d_OSXSurfaceData.h"
4632N/A
4632N/A#import <stdio.h>
4632N/A#import <JavaNativeFoundation/JavaNativeFoundation.h>
4632N/A
4632N/A#import "ImageSurfaceData.h"
4632N/A
4632N/A
4632N/A//#define DEBUG 1
4632N/A#if defined DEBUG
4632N/A #define QUARTZ_RENDERER_INLINE
4632N/A #define PRINT(msg) {fprintf(stderr, "%s\n", msg);fflush(stderr);}
4632N/A#else
4632N/A #define QUARTZ_RENDERER_INLINE static inline
4632N/A #define PRINT(msg) {}
4632N/A#endif
4632N/A
4632N/A// Copied the following from Math.java
4632N/A#define PI 3.14159265358979323846f
4632N/A
4632N/A#define BATCHED_POINTS_SIZE 1024
4632N/A
4632N/A// same value as defined in Sun's own code
4632N/A#define XOR_ALPHA_CUTOFF 128
4632N/A
4632N/A
4632N/Astatic CGFloat gRoundRectCtrlpts[10][12] =
4632N/A{
4632N/A {0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
4632N/A {0.0f, 0.0f, 1.0f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
4632N/A {0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 1.0f, 0.0f},
4632N/A {1.0f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
4632N/A {1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, -0.5f},
4632N/A {1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
4632N/A {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, -0.5f, 0.0f, 0.0f},
4632N/A {0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
4632N/A {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f},
4632N/A {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
4632N/A};
4632N/A
4632N/ACG_EXTERN CGRect CGRectApplyAffineTransform(CGRect rect, CGAffineTransform t);
4632N/A
4632N/A
4632N/ACGRect sanitizedRect(CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2) {
4632N/A CGFloat temp;
4632N/A if (x1 > x2) {
4632N/A temp = x2;
4632N/A x2 = x1;
4632N/A x1 = temp;
4632N/A }
4632N/A if (y1 > y2) {
4632N/A temp = y2;
4632N/A y2 = y1;
4632N/A y1 = temp;
4632N/A }
4632N/A return CGRectMake(x1, y1, x2-x1, y2-y1);
4632N/A}
4632N/A
4632N/AQUARTZ_RENDERER_INLINE SDRenderType doLineUsingCG(CGContextRef cgRef, CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2, BOOL simple, CGFloat offsetX, CGFloat offsetY)
4632N/A{
4632N/A//fprintf(stderr, "doLine start=(%f, %f), end=(%f, %f), linewidth:%f, offsetX:%f, offsetY:%f\n", x1, y1, x2, y2, CGContextGetLineWidth(cgRef), offsetX, offsetY);
4632N/A SDRenderType renderType = SD_Nothing;
4632N/A
4632N/A if (simple == YES)
4632N/A {
4632N/A struct CGPoint oneLinePoints[2];
4632N/A
4632N/A oneLinePoints[0] = CGPointMake(x1+offsetX, y1+offsetY);
4632N/A oneLinePoints[1] = CGPointMake(x2+offsetX, y2+offsetY);
4632N/A
4632N/A CGContextStrokeLineSegments(cgRef, oneLinePoints, 2);
4632N/A renderType = SD_Nothing;
4632N/A }
4632N/A else
4632N/A {
4632N/A CGContextMoveToPoint(cgRef, x1+offsetX, y1+offsetY);
4632N/A CGContextAddLineToPoint(cgRef, x2+offsetX, y2+offsetY);
4632N/A renderType = SD_Stroke;
4632N/A }
4632N/A
4632N/A return renderType;
4632N/A}
4632N/AQUARTZ_RENDERER_INLINE SDRenderType doLine(QuartzSDOps *qsdo, CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2)
4632N/A{
4632N/APRINT(" doLine")
4632N/A if (YES)
4632N/A {
4632N/A return doLineUsingCG(qsdo->cgRef, x1, y1, x2, y2,
4632N/A qsdo->graphicsStateInfo.simpleStroke, qsdo->graphicsStateInfo.offsetX, qsdo->graphicsStateInfo.offsetY);
4632N/A }
4632N/A // here we can add other implementations (ex. using QuickDraw, OpenGL, etc.)
4632N/A}
4632N/A
4632N/A
4632N/AQUARTZ_RENDERER_INLINE SDRenderType doRectUsingCG(CGContextRef cgRef, CGFloat x, CGFloat y, CGFloat w, CGFloat h, BOOL fill, BOOL simple, CGFloat offsetX, CGFloat offsetY)
4632N/A{
4632N/A//fprintf(stderr, "doRect point=(%f, %f), size=(%f, %f), offsets=(%f, %f) fill=%d simple=%d\n", x, y, w, h, offsetX, offsetY, fill, simple);
4632N/A//CGRect clip = CGContextGetClipBoundingBox(cgRef);
4632N/A//fprintf(stderr, " clip: ((%f, %f), (%f, %f))\n", clip.origin.x, clip.origin.y, clip.size.width, clip.size.height);
4632N/A//CGAffineTransform ctm = CGContextGetCTM(cgRef);
4632N/A//fprintf(stderr, " ctm: (%f, %f, %f, %f, %f, %f)\n", ctm.a, ctm.b, ctm.c, ctm.d, ctm.tx, ctm.ty);
4632N/A SDRenderType renderType = SD_Nothing;
4632N/A
4632N/A if (fill == YES)
4632N/A {
4632N/A if (simple == YES)
4632N/A {
4632N/A CGContextFillRect(cgRef, CGRectMake(x, y, w, h));
4632N/A renderType = SD_Nothing;
4632N/A }
4632N/A else
4632N/A {
4632N/A CGContextAddRect(cgRef, CGRectMake(x, y, w, h));
4632N/A renderType = SD_Fill;
4632N/A }
4632N/A }
4632N/A else
4632N/A {
4632N/A if (simple == YES)
4632N/A {
4632N/A CGContextStrokeRect(cgRef, CGRectMake(x+offsetX, y+offsetY, w, h));
4632N/A renderType = SD_Nothing;
4632N/A }
4632N/A else
4632N/A {
4632N/A CGContextAddRect(cgRef, CGRectMake(x+offsetX, y+offsetY, w, h));
4632N/A renderType = SD_Stroke;
4632N/A }
4632N/A }
4632N/A
4632N/A return renderType;
4632N/A}
4632N/AQUARTZ_RENDERER_INLINE SDRenderType doRect(QuartzSDOps *qsdo, CGFloat x, CGFloat y, CGFloat w, CGFloat h, BOOL fill)
4632N/A{
4632N/APRINT(" doRect")
4632N/A if (YES)
4632N/A {
4632N/A return doRectUsingCG(qsdo->cgRef, x, y, w, h, fill,
4632N/A qsdo->graphicsStateInfo.simpleStroke, qsdo->graphicsStateInfo.offsetX, qsdo->graphicsStateInfo.offsetY);
4632N/A }
4632N/A // here we can add other implementations (ex. using QuickDraw, OpenGL, etc.)
4632N/A}
4632N/A
4632N/A// from RoundRectIterator.java
4632N/AQUARTZ_RENDERER_INLINE SDRenderType doRoundRectUsingCG(CGContextRef cgRef, CGFloat x, CGFloat y, CGFloat w, CGFloat h, CGFloat arcWidth, CGFloat arcHeight, BOOL fill, CGFloat offsetX, CGFloat offsetY)
4632N/A{
4632N/A SDRenderType renderType = SD_Nothing;
4632N/A
4632N/A if (fill == YES)
4632N/A {
4632N/A renderType = SD_Fill;
4632N/A }
4632N/A else
4632N/A {
4632N/A renderType = SD_Stroke;
4632N/A }
4632N/A
4632N/A // radr://3593731 RoundRects with corner width/height of 0 don't draw
4632N/A arcWidth = (arcWidth > 0.0f) ? arcWidth : 0.0f;
4632N/A arcHeight = (arcHeight > 0.0f) ? arcHeight : 0.0f;
4632N/A
4632N/A CGFloat aw = (w < arcWidth) ? w : arcWidth;
4632N/A CGFloat ah = (h < arcHeight) ? h : arcHeight;
4632N/A
4632N/A CGFloat *ctrls, p1, q1, p2, q2, p3, q3;
4632N/A ctrls = gRoundRectCtrlpts[0];
4632N/A p1 = (x + ctrls[0] * w + ctrls[1] * aw);
4632N/A q1 = (y + ctrls[2] * h + ctrls[3] * ah);
4632N/A CGContextMoveToPoint(cgRef, p1+offsetX, q1+offsetY);
4632N/A
4632N/A ctrls = gRoundRectCtrlpts[1];
4632N/A p1 = (x + ctrls[0] * w + ctrls[1] * aw);
4632N/A q1 = (y + ctrls[2] * h + ctrls[3] * ah);
4632N/A CGContextAddLineToPoint(cgRef, p1+offsetX, q1+offsetY);
4632N/A
4632N/A ctrls = gRoundRectCtrlpts[2];
4632N/A p1 = (x + ctrls[0] * w + ctrls[1] * aw);
4632N/A q1 = (y + ctrls[2] * h + ctrls[3] * ah);
4632N/A p2 = (x + ctrls[4] * w + ctrls[5] * aw);
4632N/A q2 = (y + ctrls[6] * h + ctrls[7] * ah);
4632N/A p3 = (x + ctrls[8] * w + ctrls[9] * aw);
4632N/A q3 = (y + ctrls[10] * h + ctrls[11] * ah);
4632N/A CGContextAddCurveToPoint(cgRef, p1+offsetX, q1+offsetY, p2+offsetX, q2+offsetY, p3+offsetX, q3+offsetY);
4632N/A
4632N/A ctrls = gRoundRectCtrlpts[3];
4632N/A p1 = (x + ctrls[0] * w + ctrls[1] * aw);
4632N/A q1 = (y + ctrls[2] * h + ctrls[3] * ah);
4632N/A CGContextAddLineToPoint(cgRef, p1+offsetX, q1+offsetY);
4632N/A
4632N/A ctrls = gRoundRectCtrlpts[4];
4632N/A p1 = (x + ctrls[0] * w + ctrls[1] * aw);
4632N/A q1 = (y + ctrls[2] * h + ctrls[3] * ah);
4632N/A p2 = (x + ctrls[4] * w + ctrls[5] * aw);
4632N/A q2 = (y + ctrls[6] * h + ctrls[7] * ah);
4632N/A p3 = (x + ctrls[8] * w + ctrls[9] * aw);
4632N/A q3 = (y + ctrls[10] * h + ctrls[11] * ah);
4632N/A CGContextAddCurveToPoint(cgRef, p1+offsetX, q1+offsetY, p2+offsetX, q2+offsetY, p3+offsetX, q3+offsetY);
4632N/A
4632N/A ctrls = gRoundRectCtrlpts[5];
4632N/A p1 = (x + ctrls[0] * w + ctrls[1] * aw);
4632N/A q1 = (y + ctrls[2] * h + ctrls[3] * ah);
4632N/A CGContextAddLineToPoint(cgRef, p1+offsetX, q1+offsetY);
4632N/A
4632N/A ctrls = gRoundRectCtrlpts[6];
4632N/A p1 = (x + ctrls[0] * w + ctrls[1] * aw);
4632N/A q1 = (y + ctrls[2] * h + ctrls[3] * ah);
4632N/A p2 = (x + ctrls[4] * w + ctrls[5] * aw);
4632N/A q2 = (y + ctrls[6] * h + ctrls[7] * ah);
4632N/A p3 = (x + ctrls[8] * w + ctrls[9] * aw);
4632N/A q3 = (y + ctrls[10] * h + ctrls[11] * ah);
4632N/A CGContextAddCurveToPoint(cgRef, p1+offsetX, q1+offsetY, p2+offsetX, q2+offsetY, p3+offsetX, q3+offsetY);
4632N/A
4632N/A ctrls = gRoundRectCtrlpts[7];
4632N/A p1 = (x + ctrls[0] * w + ctrls[1] * aw);
4632N/A q1 = (y + ctrls[2] * h + ctrls[3] * ah);
4632N/A CGContextAddLineToPoint(cgRef, p1+offsetX, q1+offsetY);
4632N/A
4632N/A ctrls = gRoundRectCtrlpts[8];
4632N/A p1 = (x + ctrls[0] * w + ctrls[1] * aw);
4632N/A q1 = (y + ctrls[2] * h + ctrls[3] * ah);
4632N/A p2 = (x + ctrls[4] * w + ctrls[5] * aw);
4632N/A q2 = (y + ctrls[6] * h + ctrls[7] * ah);
4632N/A p3 = (x + ctrls[8] * w + ctrls[9] * aw);
4632N/A q3 = (y + ctrls[10] * h + ctrls[11] * ah);
4632N/A CGContextAddCurveToPoint(cgRef, p1+offsetX, q1+offsetY, p2+offsetX, q2+offsetY, p3+offsetX, q3+offsetY);
4632N/A
4632N/A CGContextClosePath(cgRef);
4632N/A
4632N/A return renderType;
4632N/A}
4632N/A
4632N/AQUARTZ_RENDERER_INLINE SDRenderType doRoundRect(QuartzSDOps *qsdo, CGFloat x, CGFloat y, CGFloat w, CGFloat h, CGFloat arcWidth, CGFloat arcHeight, BOOL fill)
4632N/A{
4632N/APRINT(" doRoundRect")
4632N/A if (YES)
4632N/A {
4632N/A return doRoundRectUsingCG(qsdo->cgRef, x, y, w, h, arcWidth, arcHeight, fill,
4632N/A qsdo->graphicsStateInfo.offsetX, qsdo->graphicsStateInfo.offsetY);
4632N/A }
4632N/A // here we can add other implementations (ex. using QuickDraw, OpenGL, etc.)
4632N/A}
4632N/A
4632N/A// from EllipseIterator.java
4632N/AQUARTZ_RENDERER_INLINE SDRenderType doOvalUsingCG(CGContextRef cgRef, CGFloat x, CGFloat y, CGFloat w, CGFloat h, BOOL fill, BOOL simple, CGFloat offsetX, CGFloat offsetY)
4632N/A{
4632N/A SDRenderType renderType = SD_Nothing;
4632N/A
4632N/A if (simple == YES)
4632N/A {
4632N/A if (fill == YES)
4632N/A {
4632N/A CGContextFillEllipseInRect(cgRef, CGRectMake(x+offsetX, y+offsetY, w, h));
4632N/A }
4632N/A else
4632N/A {
4632N/A CGContextStrokeEllipseInRect(cgRef, CGRectMake(x+offsetX, y+offsetY, w, h));
4632N/A }
4632N/A }
4632N/A else
4632N/A {
4632N/A if (fill == YES)
4632N/A {
4632N/A renderType = SD_Fill;
4632N/A }
4632N/A else
4632N/A {
4632N/A renderType = SD_Stroke;
4632N/A }
4632N/A
4632N/A CGContextAddEllipseInRect(cgRef, CGRectMake(x+offsetX, y+offsetY, w, h));
4632N/A }
4632N/A
4632N/A return renderType;
4632N/A}
4632N/AQUARTZ_RENDERER_INLINE SDRenderType doOval(QuartzSDOps *qsdo, CGFloat x, CGFloat y, CGFloat w, CGFloat h, BOOL fill)
4632N/A{
4632N/APRINT(" doOval")
4632N/A if (YES)
4632N/A {
4632N/A return doOvalUsingCG(qsdo->cgRef, x, y, w, h, fill,
4632N/A qsdo->graphicsStateInfo.simpleStroke, qsdo->graphicsStateInfo.offsetX, qsdo->graphicsStateInfo.offsetY);
4632N/A }
4632N/A // here we can add other implementations (ex. using QuickDraw, OpenGL, etc.)
4632N/A}
4632N/A
4632N/A// from ArcIterator.java
4632N/AQUARTZ_RENDERER_INLINE CGFloat btan(CGFloat increment)
4632N/A{
4632N/A increment /= 2.0f;
4632N/A CGFloat a = 1.0f - cos(increment);
4632N/A CGFloat b = tan(increment);
4632N/A CGFloat c = sqrt(1.0f + b * b) - 1.0f + a;
4632N/A
4632N/A return 4.0f / 3.0f * a * b / c;
4632N/A}
4632N/AQUARTZ_RENDERER_INLINE SDRenderType doArcUsingCG(CGContextRef cgRef, CGFloat x, CGFloat y, CGFloat w, CGFloat h, CGFloat angleStart, CGFloat angleExtent, jint arcType, BOOL fill, CGFloat offsetX, CGFloat offsetY)
4632N/A{
4632N/A//fprintf(stderr, "doArc\n");
4632N/A SDRenderType renderType = SD_Nothing;
4632N/A
4632N/A if (fill == YES)
4632N/A {
4632N/A renderType = SD_Fill;
4632N/A }
4632N/A else
4632N/A {
4632N/A renderType = SD_Stroke;
4632N/A }
4632N/A
4632N/A CGFloat angStRad, angExtDeg;
4632N/A jint arcSegs;
4632N/A jint lineSegs;
4632N/A jint index = 1;
4632N/A
4632N/A w = w / 2.0f;
4632N/A h = h / 2.0f;
4632N/A x = x + w;
4632N/A y = y + h;
4632N/A angStRad = -(angleStart / 180.0f * PI);
4632N/A angExtDeg = -angleExtent;
4632N/A CGFloat ext = (angExtDeg>0) ? angExtDeg : -angExtDeg;
4632N/A if (ext >= 360.0f)
4632N/A {
4632N/A arcSegs = 4;
4632N/A }
4632N/A else
4632N/A {
4632N/A arcSegs = (jint)ceil(ext/90.0f);
4632N/A }
4632N/A switch (arcType)
4632N/A {
4632N/A case 0:
4632N/A lineSegs = 0;
4632N/A break;
4632N/A case 1:
4632N/A lineSegs = 1;
4632N/A break;
4632N/A case 2:
4632N/A lineSegs = 2;
4632N/A break;
4632N/A }
4632N/A if (w < 0 || h < 0)
4632N/A {
4632N/A arcSegs = lineSegs = -1;
4632N/A }
4632N/A
4632N/A CGFloat angle = angStRad;
4632N/A CGContextMoveToPoint(cgRef, (x + cos(angle) * w)+offsetX, (y + sin(angle) * h)+offsetY);
4632N/A
4632N/A CGFloat increment = angExtDeg;
4632N/A if (increment > 360.0f)
4632N/A {
4632N/A increment = 360.0f;
4632N/A }
4632N/A else if (increment < -360.0f)
4632N/A {
4632N/A increment = -360.0f;
4632N/A }
4632N/A increment /= arcSegs;
4632N/A increment = (increment / 180.0f * PI);
4632N/A CGFloat z = btan(increment);
4632N/A CGFloat angleBase = angle;
4632N/A CGFloat p1, q1, p2, q2, p3, q3;
4632N/A while (index <= arcSegs)
4632N/A {
4632N/A angle = angleBase + increment * (index - 1);
4632N/A CGFloat relx = cos(angle);
4632N/A CGFloat rely = sin(angle);
4632N/A p1 = (x + (relx - z * rely) * w);
4632N/A q1 = (y + (rely + z * relx) * h);
4632N/A angle += increment;
4632N/A relx = cos(angle);
4632N/A rely = sin(angle);
4632N/A p2 = (x + (relx + z * rely) * w);
4632N/A q2 = (y + (rely - z * relx) * h);
4632N/A p3 = (x + relx * w);
4632N/A q3 = (y + rely * h);
4632N/A
4632N/A CGContextAddCurveToPoint(cgRef, p1+offsetX, q1+offsetY, p2+offsetX, q2+offsetY, p3+offsetX, q3+offsetY);
4632N/A
4632N/A index++;
4632N/A }
4632N/A
4632N/A switch (arcType)
4632N/A {
4632N/A case 1:
4632N/A CGContextClosePath(cgRef);
4632N/A break;
4632N/A case 2:
4632N/A CGContextAddLineToPoint(cgRef, x+offsetX, y+offsetY);
4632N/A CGContextClosePath(cgRef);
4632N/A break;
4632N/A default:
4632N/A break;
4632N/A }
4632N/A
4632N/A return renderType;
4632N/A}
4632N/AQUARTZ_RENDERER_INLINE SDRenderType doArc(QuartzSDOps *qsdo, CGFloat x, CGFloat y, CGFloat w, CGFloat h, CGFloat angleStart, CGFloat angleExtent, jint arcType, BOOL fill)
4632N/A{
4632N/APRINT(" doArc")
4632N/A if (YES)
4632N/A {
4632N/A return doArcUsingCG(qsdo->cgRef, x, y, w, h, angleStart, angleExtent, arcType, fill,
4632N/A qsdo->graphicsStateInfo.offsetX, qsdo->graphicsStateInfo.offsetY);
4632N/A }
4632N/A // here we can add other implementations (ex. using QuickDraw, OpenGL, etc.)
4632N/A}
4632N/A
4632N/AQUARTZ_RENDERER_INLINE SDRenderType doPolyUsingCG(JNIEnv *env, CGContextRef cgRef, jintArray xpointsarray, jintArray ypointsarray, jint npoints, BOOL polygon, BOOL fill, CGFloat offsetX, CGFloat offsetY)
4632N/A{
4632N/A SDRenderType renderType = SD_Nothing;
4632N/A
4632N/A if (npoints > 1)
4632N/A {
4632N/A if (fill == YES)
4632N/A {
4632N/A renderType = SD_Fill;
4632N/A }
4632N/A else
4632N/A {
4632N/A renderType = SD_Stroke;
4632N/A }
4632N/A
4632N/A jint i;
4632N/A
4632N/A jint* xpoints = (jint*)(*env)->GetPrimitiveArrayCritical(env, xpointsarray, NULL);
4632N/A jint* ypoints = (jint*)(*env)->GetPrimitiveArrayCritical(env, ypointsarray, NULL);
4632N/A
4632N/A CGContextMoveToPoint(cgRef, xpoints[0]+offsetX, ypoints[0]+offsetY);
4632N/A
4632N/A for (i=1; i<npoints; i++)
4632N/A {
4632N/A CGContextAddLineToPoint(cgRef, xpoints[i]+offsetX, ypoints[i]+offsetY);
4632N/A }
4632N/A
4632N/A if (polygon == YES)
4632N/A {
4632N/A if ((xpoints[0] != xpoints[npoints-1]) || (ypoints[0] != ypoints[npoints-1])) // according to the specs (only applies to polygons, not polylines)
4632N/A {
4632N/A CGContextAddLineToPoint(cgRef, xpoints[0]+offsetX, ypoints[0]+offsetY);
4632N/A }
4632N/A }
4632N/A
4632N/A (*env)->ReleasePrimitiveArrayCritical(env, ypointsarray, ypoints, 0);
4632N/A (*env)->ReleasePrimitiveArrayCritical(env, xpointsarray, xpoints, 0);
4632N/A }
4632N/A
4632N/A return renderType;
4632N/A}
4632N/AQUARTZ_RENDERER_INLINE SDRenderType doPoly(JNIEnv *env, QuartzSDOps *qsdo, jintArray xpointsarray, jintArray ypointsarray, jint npoints, BOOL polygon, BOOL fill)
4632N/A{
4632N/APRINT(" doPoly")
4632N/A if (YES)
4632N/A {
4632N/A return doPolyUsingCG(env, qsdo->cgRef, xpointsarray, ypointsarray, npoints, polygon, fill,
4632N/A qsdo->graphicsStateInfo.offsetX, qsdo->graphicsStateInfo.offsetY);
4632N/A }
4632N/A // here we can add other implementations (ex. using QuickDraw, OpenGL, etc.)
4632N/A}
4632N/A
4632N/ASDRenderType doShape(QuartzSDOps *qsdo, jint *types, jfloat *coords, jint numtypes, BOOL fill, BOOL shouldApplyOffset)
4632N/A{
4632N/APRINT(" doShape")
4632N/A if (YES)
4632N/A {
4632N/A CGFloat offsetX = 0.0f;
4632N/A CGFloat offsetY = 0.0f;
4632N/A if (shouldApplyOffset)
4632N/A {
4632N/A offsetX = qsdo->graphicsStateInfo.offsetX;
4632N/A offsetY = qsdo->graphicsStateInfo.offsetY;
4632N/A }
4632N/A return DoShapeUsingCG(qsdo->cgRef, types, coords, numtypes, fill, offsetX, offsetY); // defined in QuartzSurfaceData.m
4632N/A }
4632N/A // here we can add other implementations (ex. using QuickDraw, OpenGL, etc.)
4632N/A}
4632N/A
4632N/A
4632N/A
4632N/AQUARTZ_RENDERER_INLINE void doImageCG(JNIEnv *env, CGContextRef cgRef, jobject imageSurfaceData,
4632N/A jint interpolation, BOOL fliph, BOOL flipv, jint w, jint h, jint sx, jint sy, jint sw, jint sh, jint dx, jint dy, jint dw, jint dh)
4632N/A{
4632N/A//fprintf(stderr, "doImageCG\n");
4632N/A//fprintf(stderr, " flip:(%d, %d), size:(%d, %d), src:(%d, %d, %d, %d), dst:(%d, %d, %d, %d)\n", (jint)fliph, (jint)flipv, w, h, sx, sy, sw, sh, dx, dy, dw, dh);
4632N/A // gznote: need to handle interpolation
4632N/A ImageSDOps* isdo = LockImage(env, imageSurfaceData);
4632N/A
4632N/A CGFloat a = 1.0f;
4632N/A CGFloat b = 0.0f;
4632N/A CGFloat c = 0.0f;
4632N/A CGFloat d = -1.0f;
4632N/A CGFloat tx = dx;
4632N/A CGFloat ty = dy+dh;
4632N/A
4632N/A if (flipv == YES)
4632N/A {
4632N/A d = 1.0f;
4632N/A ty -= dh;
4632N/A }
4632N/A if (fliph == YES)
4632N/A {
4632N/A a = -1.0f;
4632N/A tx += dw;
4632N/A }
4632N/A
4632N/A makeSureImageIsCreated(isdo);
4632N/A
5321N/A CGContextSaveGState(cgRef);
4632N/A CGContextConcatCTM(cgRef, CGAffineTransformMake(a, b, c, d, tx, ty));
4632N/A jint alphaInfo = isdo->contextInfo.alphaInfo & kCGBitmapAlphaInfoMask;
4632N/A
4632N/A if ((sx == 0) && (sy == 0) && (sw == w) && (sh == h)) // no subimages allowed here
4632N/A {
4632N/A CGContextDrawImage(cgRef, CGRectMake(0, 0, dw, dh), isdo->imgRef);
4632N/A }
4632N/A else // handle subimages
4632N/A {
4632N/A CGImageRef subImg = CGImageCreateWithImageInRect(isdo->imgRef, CGRectMake(sx, sy, sw, sh));
4632N/A CGContextDrawImage(cgRef, CGRectMake(0.0f, 0.0f, dw, dh), subImg);
4632N/A CGImageRelease(subImg);
4632N/A }
4632N/A
5321N/A CGContextRestoreGState(cgRef);
4632N/A UnlockImage(env, isdo);
4632N/A}
4632N/A
4632N/AQUARTZ_RENDERER_INLINE void doImage(JNIEnv *env, QuartzSDOps *qsdo, jobject imageSurfaceData,
4632N/A jboolean fliph, jboolean flipv, jint w, jint h, jint sx, jint sy, jint sw, jint sh, jint dx, jint dy, jint dw, jint dh)
4632N/A{
4632N/A if ((w > 0) && (h > 0) && (sw > 0) && (sh > 0) && (dw > 0) && (dh > 0))
4632N/A {
4632N/A doImageCG(env, qsdo->cgRef, imageSurfaceData,
4632N/A qsdo->graphicsStateInfo.interpolation, (BOOL)fliph, (BOOL)flipv, (jint)w, (jint)h, (jint)sx, (jint)sy, (jint)sw, (jint)sh, (jint)dx, (jint)dy, (jint)dw, (jint)dh);
4632N/A }
4632N/A}
4632N/A
4632N/A
4632N/A
4632N/AQUARTZ_RENDERER_INLINE void completePath(JNIEnv *env, QuartzSDOps *qsdo, CGContextRef cgRef, jint renderType)
4632N/A{
4632N/A switch (renderType)
4632N/A {
4632N/A case SD_Stroke:
4632N/A if (CGContextIsPathEmpty(cgRef) == 0)
4632N/A {
4632N/A CGContextStrokePath(cgRef);
4632N/A }
4632N/A break;
4632N/A case SD_Fill:
4632N/A if (CGContextIsPathEmpty(cgRef) == 0)
4632N/A {
4632N/A CGContextFillPath(cgRef);
4632N/A }
4632N/A break;
4632N/A case SD_Image:
4632N/A break;
4632N/A case SD_Nothing:
4632N/A break;
4632N/A default:
4632N/Afprintf(stderr, "completePath unknown renderType=%d\n", (int)renderType);
4632N/A break;
4632N/A }
4632N/A}
4632N/A
4632N/A/*
4632N/A * Class: sun_java2d_CRenderer
4632N/A * Method: init
4632N/A * Signature: ()V
4632N/A */
4632N/AJNIEXPORT void JNICALL Java_sun_java2d_CRenderer_init
4632N/A(JNIEnv *env, jobject jthis)
4632N/A{
4632N/APRINT("Java_sun_java2d_CRenderer_init")
4632N/A CGFloat angle = PI / 4.0f;
4632N/A CGFloat a = 1.0f - cos(angle);
4632N/A CGFloat b = tan(angle);
4632N/A CGFloat c = sqrt(1.0f + b * b) - 1.0f + a;
4632N/A CGFloat cv = 4.0f / 3.0f * a * b / c;
4632N/A CGFloat acv = (1.0f - cv) / 2.0f;
4632N/A
4632N/A gRoundRectCtrlpts[2][3] = -acv;
4632N/A gRoundRectCtrlpts[2][5] = acv;
4632N/A gRoundRectCtrlpts[4][1] = -acv;
4632N/A gRoundRectCtrlpts[4][7] = -acv;
4632N/A gRoundRectCtrlpts[6][3] = acv;
4632N/A gRoundRectCtrlpts[6][5] = -acv;
4632N/A gRoundRectCtrlpts[8][1] = acv;
4632N/A gRoundRectCtrlpts[8][7] = acv;
4632N/A}
4632N/A
4632N/A/*
4632N/A * Class: sun_java2d_CRenderer
4632N/A * Method: doLine
4632N/A * Signature: (Lsun/java2d/SurfaceData;Ljava/nio/IntBuffer;Ljava/nio/FloatBuffer;[Ljava/lang/Object;FFFF)V
4632N/A */
4632N/AJNIEXPORT void JNICALL Java_sun_java2d_CRenderer_doLine
4632N/A(JNIEnv *env, jobject jthis, jobject jsurfacedata, jfloat x1, jfloat y1, jfloat x2, jfloat y2)
4632N/A{
4632N/APRINT("Java_sun_java2d_CRenderer_doLine")
4632N/A QuartzSDOps *qsdo = (QuartzSDOps*)SurfaceData_GetOps(env, jsurfacedata);
4632N/AJNF_COCOA_ENTER(env);
4632N/A SDRenderType renderType = SD_Stroke;
4632N/A qsdo->BeginSurface(env, qsdo, renderType);
4632N/A if (qsdo->cgRef != NULL)
4632N/A {
4632N/A doLine(qsdo, x1, y1, x2, y2);
4632N/A }
4632N/A qsdo->FinishSurface(env, qsdo);
4632N/AJNF_COCOA_RENDERER_EXIT(env);
4632N/A}
4632N/A
4632N/A/*
4632N/A * Class: sun_java2d_CRenderer
4632N/A * Method: doRect
4632N/A * Signature: (Lsun/java2d/SurfaceData;Ljava/nio/IntBuffer;Ljava/nio/FloatBuffer;[Ljava/lang/Object;FFFF)V
4632N/A */
4632N/AJNIEXPORT void JNICALL Java_sun_java2d_CRenderer_doRect
4632N/A(JNIEnv *env, jobject jthis, jobject jsurfacedata, jfloat x, jfloat y, jfloat w, jfloat h, jboolean isfill)
4632N/A{
4632N/APRINT("Java_sun_java2d_CRenderer_doRect")
4632N/A QuartzSDOps *qsdo = (QuartzSDOps*)SurfaceData_GetOps(env, jsurfacedata);
4632N/AJNF_COCOA_ENTER(env);
4632N/A SDRenderType renderType = (isfill? SD_Fill : SD_Stroke);
4632N/A qsdo->BeginSurface(env, qsdo, renderType);
4632N/A if (qsdo->cgRef != NULL)
4632N/A {
4632N/A doRect(qsdo, x, y, w, h, isfill);
4632N/A }
4632N/A qsdo->FinishSurface(env, qsdo);
4632N/AJNF_COCOA_RENDERER_EXIT(env);
4632N/A}
4632N/A
4632N/A/*
4632N/A * Class: sun_java2d_CRenderer
4632N/A * Method: doRoundRect
4632N/A * Signature: (Lsun/java2d/SurfaceData;Ljava/nio/IntBuffer;Ljava/nio/FloatBuffer;[Ljava/lang/Object;IIIIII)V
4632N/A */
4632N/AJNIEXPORT void JNICALL Java_sun_java2d_CRenderer_doRoundRect
4632N/A(JNIEnv *env, jobject jthis, jobject jsurfacedata, jfloat x, jfloat y, jfloat w, jfloat h, jfloat arcWidth, jfloat arcHeight, jboolean isfill)
4632N/A{
4632N/APRINT("Java_sun_java2d_CRenderer_doRoundRect")
4632N/A QuartzSDOps *qsdo = (QuartzSDOps*)SurfaceData_GetOps(env, jsurfacedata);
4632N/AJNF_COCOA_ENTER(env);
4632N/A SDRenderType renderType = (isfill? SD_Fill : SD_Stroke);
4632N/A qsdo->BeginSurface(env, qsdo, renderType);
4632N/A if (qsdo->cgRef != NULL)
4632N/A {
4632N/A doRoundRect(qsdo, x, y, w, h, arcWidth, arcHeight, isfill);
4632N/A }
4632N/A qsdo->FinishSurface(env, qsdo);
4632N/AJNF_COCOA_RENDERER_EXIT(env);
4632N/A}
4632N/A
4632N/A/*
4632N/A * Class: sun_java2d_CRenderer
4632N/A * Method: doOval
4632N/A * Signature: (Lsun/java2d/SurfaceData;Ljava/nio/IntBuffer;Ljava/nio/FloatBuffer;[Ljava/lang/Object;IIII)V
4632N/A */
4632N/AJNIEXPORT void JNICALL Java_sun_java2d_CRenderer_doOval
4632N/A(JNIEnv *env, jobject jthis, jobject jsurfacedata, jfloat x, jfloat y, jfloat w, jfloat h, jboolean isfill)
4632N/A{
4632N/APRINT("Java_sun_java2d_CRenderer_doOval")
4632N/A QuartzSDOps *qsdo = (QuartzSDOps*)SurfaceData_GetOps(env, jsurfacedata);
4632N/AJNF_COCOA_ENTER(env);
4632N/A SDRenderType renderType = (isfill? SD_Fill : SD_Stroke);
4632N/A qsdo->BeginSurface(env, qsdo, renderType);
4632N/A if (qsdo->cgRef != NULL)
4632N/A {
4632N/A doOval(qsdo, x, y, w, h, isfill);
4632N/A }
4632N/A qsdo->FinishSurface(env, qsdo);
4632N/AJNF_COCOA_RENDERER_EXIT(env);
4632N/A}
4632N/A
4632N/A/*
4632N/A * Class: sun_java2d_CRenderer
4632N/A * Method: doArc
4632N/A * Signature: (Lsun/java2d/SurfaceData;Ljava/nio/IntBuffer;Ljava/nio/FloatBuffer;[Ljava/lang/Object;IIIIII)V
4632N/A */
4632N/AJNIEXPORT void JNICALL Java_sun_java2d_CRenderer_doArc
4632N/A(JNIEnv *env, jobject jthis, jobject jsurfacedata, jfloat x, jfloat y, jfloat w, jfloat h, jfloat angleStart, jfloat angleExtent, jint arcType, jboolean isfill)
4632N/A{
4632N/APRINT("Java_sun_java2d_CRenderer_doArc")
4632N/A QuartzSDOps *qsdo = (QuartzSDOps*)SurfaceData_GetOps(env, jsurfacedata);
4632N/AJNF_COCOA_ENTER(env);
4632N/A SDRenderType renderType = (isfill? SD_Fill : SD_Stroke);
4632N/A qsdo->BeginSurface(env, qsdo, renderType);
4632N/A if (qsdo->cgRef != NULL)
4632N/A {
4632N/A doArc(qsdo, x, y, w, h, angleStart, angleExtent, arcType, isfill);
4632N/A }
4632N/A qsdo->FinishSurface(env, qsdo);
4632N/AJNF_COCOA_RENDERER_EXIT(env);
4632N/A}
4632N/A
4632N/A/*
4632N/A * Class: sun_java2d_CRenderer
4632N/A * Method: doPoly
4632N/A * Signature:
4632N/A */
4632N/AJNIEXPORT void JNICALL Java_sun_java2d_CRenderer_doPoly
4632N/A(JNIEnv *env, jobject jthis, jobject jsurfacedata, jintArray xpointsarray, jintArray ypointsarray, jint npoints, jboolean ispolygon, jboolean isfill)
4632N/A{
4632N/APRINT("Java_sun_java2d_CRenderer_doPoly")
4632N/A QuartzSDOps *qsdo = (QuartzSDOps*)SurfaceData_GetOps(env, jsurfacedata);
4632N/AJNF_COCOA_ENTER(env);
4632N/A BOOL eoFill = YES; // polys are WIND_EVEN_ODD by definition
4632N/A SDRenderType renderType = (isfill? (eoFill ? SD_EOFill : SD_Fill) : SD_Stroke);
4632N/A qsdo->BeginSurface(env, qsdo, renderType);
4632N/A if (qsdo->cgRef != NULL)
4632N/A {
4632N/A doPoly(env, qsdo, xpointsarray, ypointsarray, npoints, ispolygon, isfill);
4632N/A }
4632N/A qsdo->FinishSurface(env, qsdo);
4632N/AJNF_COCOA_RENDERER_EXIT(env);
4632N/A}
4632N/A
4632N/A/*
4632N/A * Class: sun_java2d_CRenderer
4632N/A * Method: doShape
4632N/A * Signature: (Lsun/java2d/SurfaceData;Ljava/nio/IntBuffer;Ljava/nio/FloatBuffer;[Ljava/lang/Object;ILjava/nio/FloatBuffer;Ljava/nio/IntBuffer;IZ)V
4632N/A */
4632N/AJNIEXPORT void JNICALL Java_sun_java2d_CRenderer_doShape
4632N/A(JNIEnv *env, jobject jthis, jobject jsurfacedata, jint length, jobject jFloatCoordinates, jobject jIntTypes, jint windingRule, jboolean isfill, jboolean shouldApplyOffset)
4632N/A{
4632N/APRINT("Java_sun_java2d_CRenderer_doShape")
4632N/A QuartzSDOps *qsdo = (QuartzSDOps*)SurfaceData_GetOps(env, jsurfacedata);
4632N/AJNF_COCOA_ENTER(env);
4632N/A BOOL eoFill = (windingRule == java_awt_geom_PathIterator_WIND_EVEN_ODD);
4632N/A SDRenderType renderType = (isfill? (eoFill ? SD_EOFill : SD_Fill) : SD_Stroke);
4632N/A qsdo->BeginSurface(env, qsdo, renderType);
4632N/A if (qsdo->cgRef != NULL)
4632N/A {
4632N/A jfloat *coordinates = (jfloat*)((*env)->GetDirectBufferAddress(env, jFloatCoordinates));
4632N/A jint *types = (jint*)((*env)->GetDirectBufferAddress(env, jIntTypes));
4632N/A doShape(qsdo, types, coordinates, length, isfill, shouldApplyOffset);
4632N/A }
4632N/A qsdo->FinishSurface(env, qsdo);
4632N/AJNF_COCOA_RENDERER_EXIT(env);
4632N/A}
4632N/A
4632N/A#define invalidContext(c) \
4632N/A ((c) == NULL /* || (c)->identifer != CGContextIdentifier */)
4632N/A
4632N/A/*
4632N/A * Class: sun_java2d_CRenderer
4632N/A * Method: doImage
4632N/A * Signature: (Lsun/java2d/SurfaceData;Ljava/nio/IntBuffer;Ljava/nio/FloatBuffer;[Ljava/lang/Object;Lsun/java2d/SurfaceData;ZZIIIIIIII)V
4632N/A */
4632N/AJNIEXPORT void JNICALL Java_sun_java2d_CRenderer_doImage
4632N/A(JNIEnv *env, jobject jthis, jobject jsurfacedata, jobject imageSurfaceData, jboolean fliph, jboolean flipv, jint w, jint h, jint sx, jint sy, jint sw, jint sh, jint dx, jint dy, jint dw, jint dh)
4632N/A{
4632N/APRINT("Java_sun_java2d_CRenderer_doImage")
4632N/A QuartzSDOps *qsdo = (QuartzSDOps*)SurfaceData_GetOps(env, jsurfacedata);
4632N/AJNF_COCOA_ENTER(env);
4632N/A qsdo->BeginSurface(env, qsdo, SD_Image);
4632N/A if (qsdo->cgRef != NULL)
4632N/A {
4632N/A doImage(env, qsdo, imageSurfaceData, fliph, flipv, w, h, sx, sy, sw, sh, dx, dy, dw, dh);
4632N/A }
4632N/A qsdo->FinishSurface(env, qsdo);
4632N/AJNF_COCOA_RENDERER_EXIT(env);
4632N/A}