/* * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ #import "CGGlyphOutlines.h" static void AWTPathGetMoreSpaceIfNecessary(AWTPathRef path) { while ((path->fAllocatedSegmentTypeSpace - path->fNumberOfSegments) < 1) { size_t growth = sizeof(jbyte)*path->fAllocatedSegmentTypeSpace*kStorageSizeChangeOnGetMoreFactor; path->fSegmentType = (jbyte*) realloc(path->fSegmentType, growth); path->fAllocatedSegmentTypeSpace *= kStorageSizeChangeOnGetMoreFactor; } while ((path->fAllocatedSegmentDataSpace - path->fNumberOfDataElements) < 7) { size_t growth = sizeof(jfloat)*path->fAllocatedSegmentDataSpace*kStorageSizeChangeOnGetMoreFactor; path->fSegmentData = (jfloat*) realloc(path->fSegmentData, growth); path->fAllocatedSegmentDataSpace *= kStorageSizeChangeOnGetMoreFactor; } } static void AWTPathMoveTo(void* data, CGPoint p) { CGFloat x = p.x; CGFloat y = p.y; AWTPathRef path = (AWTPathRef)data; CGFloat tx = path->fTranslate.width; CGFloat ty = path->fTranslate.height; CGFloat pathX = x+tx; CGFloat pathY = -y+ty; #ifdef AWT_GV_DEBUG fprintf(stderr, "eMoveTo \n"); fprintf(stderr, " tx=%f, ty=%f\n", tx, ty); fprintf(stderr, " x=%f, y=%f\n", x, y); fprintf(stderr, " pathX=%f, pathY=%f\n", pathX, pathY); #endif AWTPathGetMoreSpaceIfNecessary(path); path->fSegmentType[path->fNumberOfSegments++] = (jbyte)eMoveTo; path->fSegmentData[path->fNumberOfDataElements++] = pathX; path->fSegmentData[path->fNumberOfDataElements++] = pathY; } static void AWTPathLineTo(void* data, CGPoint p) { CGFloat x = p.x; CGFloat y = p.y; AWTPathRef path = (AWTPathRef)data; CGFloat tx = path->fTranslate.width; CGFloat ty = path->fTranslate.height; CGFloat pathX = x+tx; CGFloat pathY = -y+ty; #ifdef AWT_GV_DEBUG fprintf(stderr, "eLineTo \n"); fprintf(stderr, " tx=%f, ty=%f\n", tx, ty); fprintf(stderr, " x=%f, y=%f\n", x, y); fprintf(stderr, " pathX=%f, pathY=%f\n", pathX, pathY); #endif AWTPathGetMoreSpaceIfNecessary(path); path->fSegmentType[path->fNumberOfSegments++] = (jbyte)eLineTo; path->fSegmentData[path->fNumberOfDataElements++] = pathX; path->fSegmentData[path->fNumberOfDataElements++] = pathY; } static void AWTPathQuadTo(void* data, CGPoint p1, CGPoint p2) { CGFloat x1 = p1.x; CGFloat y1 = p1.y; CGFloat x2 = p2.x; CGFloat y2 = p2.y; AWTPathRef path = (AWTPathRef)data; CGFloat tx = path->fTranslate.width; CGFloat ty = path->fTranslate.height; CGFloat pathX1 = x1+tx; CGFloat pathY1 = -y1+ty; CGFloat pathX2 = x2+tx; CGFloat pathY2 = -y2+ty; #ifdef AWT_GV_DEBUG fprintf(stderr, "eQuadTo \n"); fprintf(stderr, " tx=%f, ty=%f\n", tx, ty); fprintf(stderr, " x1=%f, y1=%f\n", x1, y1); fprintf(stderr, " x2=%f, y2=%f\n", x2, y2); fprintf(stderr, " pathX1=%f, path1Y=%f\n", pathX1, pathY1); fprintf(stderr, " pathX2=%f, pathY2=%f\n", pathX2, pathY2); #endif AWTPathGetMoreSpaceIfNecessary(path); path->fSegmentType[path->fNumberOfSegments++] = (jbyte)eQuadTo; path->fSegmentData[path->fNumberOfDataElements++] = pathX1; path->fSegmentData[path->fNumberOfDataElements++] = pathY1; path->fSegmentData[path->fNumberOfDataElements++] = pathX2; path->fSegmentData[path->fNumberOfDataElements++] = pathY2; } static void AWTPathCubicTo(void* data, CGPoint p1, CGPoint p2, CGPoint p3) { CGFloat x1 = p1.x; CGFloat y1 = p1.y; CGFloat x2 = p2.x; CGFloat y2 = p2.y; CGFloat x3 = p3.x; CGFloat y3 = p3.y; AWTPathRef path = (AWTPathRef)data; CGFloat tx = path->fTranslate.width; CGFloat ty = path->fTranslate.height; CGFloat pathX1 = x1+tx; CGFloat pathY1 = -y1+ty; CGFloat pathX2 = x2+tx; CGFloat pathY2 = -y2+ty; CGFloat pathX3 = x3+tx; CGFloat pathY3 = -y3+ty; #ifdef AWT_GV_DEBUG fprintf(stderr, "eCubicTo \n"); fprintf(stderr, " tx=%f, ty=%f\n", tx, ty); fprintf(stderr, " x1=%f, y1=%f\n", x1, y1); fprintf(stderr, " x2=%f, y2=%f\n", x2, y2); fprintf(stderr, " x3=%f, y3=%f\n", x3, y3); fprintf(stderr, " pathX1=%f, path1Y=%f\n", pathX1, pathY1); fprintf(stderr, " pathX2=%f, pathY2=%f\n", pathX2, pathY2); fprintf(stderr, " pathX3=%f, pathY3=%f\n", pathX3, pathY3); #endif AWTPathGetMoreSpaceIfNecessary(path); path->fSegmentType[path->fNumberOfSegments++] = (jbyte)eCubicTo; path->fSegmentData[path->fNumberOfDataElements++] = pathX1; path->fSegmentData[path->fNumberOfDataElements++] = pathY1; path->fSegmentData[path->fNumberOfDataElements++] = pathX2; path->fSegmentData[path->fNumberOfDataElements++] = pathY2; path->fSegmentData[path->fNumberOfDataElements++] = pathX3; path->fSegmentData[path->fNumberOfDataElements++] = pathY3; } static void AWTPathClose(void* data) { #ifdef AWT_GV_DEBUG fprintf(stderr, "GVGlyphPathCallBackClosePath \n"); #endif AWTPathRef path = (AWTPathRef) data; AWTPathGetMoreSpaceIfNecessary(path); path->fSegmentType[path->fNumberOfSegments++] = (jbyte)eClosePath; } AWTPathRef AWTPathCreate(CGSize translate) { #ifdef AWT_GV_DEBUG fprintf(stderr, "AWTPathCreate \n"); fprintf(stderr, " translate.width=%f \n", translate.width); fprintf(stderr, " translate.height=%f \n", translate.height); #endif AWTPathRef path = (AWTPathRef) malloc(sizeof(AWTPath)); path->fTranslate = translate; path->fSegmentData = (jfloat*)malloc(sizeof(jfloat) * kInitialAllocatedPathSegments); path->fSegmentType = (jbyte*)malloc(sizeof(jbyte) * kInitialAllocatedPathSegments); path->fNumberOfDataElements = 0; path->fNumberOfSegments = 0; path->fAllocatedSegmentTypeSpace = kInitialAllocatedPathSegments; path->fAllocatedSegmentDataSpace = kInitialAllocatedPathSegments; return path; } void AWTPathFree(AWTPathRef pathRef) { #ifdef AWT_GV_DEBUG fprintf(stderr, "--B--AWTPathFree\n"); fprintf(stderr, "pathRef->fSegmentData (%p)\n",pathRef->fSegmentData); #endif free(pathRef->fSegmentData); //fprintf(stderr, "pathRef->fSegmentType (%d)\n",pathRef->fSegmentType); free(pathRef->fSegmentType); //fprintf(stderr, "pathRef (%d)\n", pathRef); free(pathRef); //fprintf(stderr, "--E--AWTPathFree\n"); } static void AWTPathApplierCallback(void *info, const CGPathElement *element) { switch (element->type) { case kCGPathElementMoveToPoint: AWTPathMoveTo(info, element->points[0]); break; case kCGPathElementAddLineToPoint: AWTPathLineTo(info, element->points[0]); break; case kCGPathElementAddQuadCurveToPoint: AWTPathQuadTo(info, element->points[0], element->points[1]); break; case kCGPathElementAddCurveToPoint: AWTPathCubicTo(info, element->points[0], element->points[1], element->points[2]); break; case kCGPathElementCloseSubpath: AWTPathClose(info); break; } } OSStatus AWTGetGlyphOutline(CGGlyph *glyphs, NSFont *font, CGSize *advanceArray, CGAffineTransform *tx, UInt32 inStartIndex, size_t length, AWTPathRef* outPath) { #ifdef AWT_GV_DEBUG fprintf(stderr, "AWTGetGlyphOutline\n"); fprintf(stderr, " inAffineTransform a=%f, b=%f, c=%f, d=%f, tx=%f, ty=%f \n", tx->a, tx->b, tx->c, tx->d, tx->tx, tx->ty); #endif OSStatus status = noErr; glyphs = glyphs + inStartIndex; // advanceArray = advanceArray + inStartIndex; // TODO(cpc): use advance CGPathRef cgPath = CTFontCreatePathForGlyph((CTFontRef)font, glyphs[0], tx); CGPathApply(cgPath, *outPath, AWTPathApplierCallback); CGPathRelease(cgPath); return status; }