2013-06-25 17:13:37 +00:00
/ *
OpalGState . m
Copyright ( C ) 2013 Free Software Foundation , Inc .
Author : Ivan Vucica < ivan @ vucica . net >
Date : June 2013
This file is part of GNUstep .
This library is free software ; you can redistribute it and / or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation ; either
version 2 of the License , or ( at your option ) any later version .
This library 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
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public
License along with this library ; see the file COPYING . LIB .
If not , see < http : // www . gnu . org / licenses / > or write to the
Free Software Foundation , 51 Franklin Street , Fifth Floor ,
Boston , MA 02110 -1301 , USA .
* /
2013-07-11 20:44:32 +00:00
# import < CoreGraphics / CoreGraphics . h >
# import < X11 / Xlib . h >
2013-08-01 22:28:57 +00:00
# import < AppKit / NSGraphics . h > // NS * ColorSpace
2013-06-25 17:13:37 +00:00
# import "opal/OpalGState.h"
2013-07-11 20:44:32 +00:00
# import "opal/OpalSurface.h"
* Source/opal/OpalFontInfo.m: Move font space to user space conversion
to a separate method. Implement -glyphIsEncoded:, -advancementForGlyph:,
-glyphForCharacter:, -glyphWithName:.
For -boundingRectForGlyph:, and -widthOfString:, return fake, fixed
values.
* Source/opal/OpalContext.m: Fix -isDrawingToScreen implementation;
it now returns YES. This has the unfortunate side effect of breaking
image drawing... but, on the positive side, causes NSLayoutManager
to make calls to GSShowGlyphsWithAdvances in batches of up to
16 glyphs, instead of one at a time...!
* Source/opal/OpalGState.m: Implement -GSSetFont:, and make
-GSShowGlyphsWithAdvances: call CGContextShowGlyphsWithAdvances
Overall state is glyphs are drawn.. they appear upside down,
and the glyph runs only seem to draw at (0, 0).
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@37087 72102866-910b-0410-8b05-ffd578937521
2013-09-17 06:53:08 +00:00
# import "opal/OpalFontInfo.h"
2013-07-11 20:44:32 +00:00
# import "x11/XGServerWindow.h"
2013-06-25 17:13:37 +00:00
2013-09-23 18:04:06 +00:00
# define CGCTX [ self CGContext ]
2013-07-15 15:24:04 +00:00
2013-09-23 18:04:06 +00:00
static inline NSString * _CGRectRepr ( CGRect rect )
{
return [ NSString stringWithFormat : @ "(%g,%g,%g,%g)" ,
rect . origin . x , rect . origin . y ,
rect . size . width , rect . size . height ] ;
}
static inline CGRect _CGRectFromNSRect ( NSRect nsrect )
{
return CGRectMake ( nsrect . origin . x , nsrect . origin . y ,
nsrect . size . width , nsrect . size . height ) ;
}
2013-07-23 23:18:48 +00:00
2013-06-25 17:13:37 +00:00
@ implementation OpalGState
2013-07-11 20:44:32 +00:00
// MARK : Minimum required methods
// MARK : -
2013-06-25 17:13:37 +00:00
- ( void ) DPSinitclip
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-07-15 15:24:04 +00:00
OPContextResetClip ( CGCTX ) ;
2013-06-25 17:13:37 +00:00
}
- ( void ) DPSclip
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-07-15 15:24:04 +00:00
CGContextClip ( CGCTX ) ;
2013-06-25 17:13:37 +00:00
}
- ( void ) DPSfill
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-07-15 15:24:04 +00:00
2013-07-25 14:49:44 +00:00
CGContextFillPath ( CGCTX ) ;
2013-06-25 17:13:37 +00:00
}
- ( void ) DPSimage : ( NSAffineTransform * ) matrix
: ( NSInteger ) pixelsWide
: ( NSInteger ) pixelsHigh
2013-08-01 22:28:57 +00:00
: ( NSInteger ) bitsPerSample // is this used correctly ?
: ( NSInteger ) samplesPerPixel // < unused
2013-06-25 17:13:37 +00:00
: ( NSInteger ) bitsPerPixel
: ( NSInteger ) bytesPerRow
2013-08-01 22:28:57 +00:00
: ( BOOL ) isPlanar // < unused
: ( BOOL ) hasAlpha // < unused
2013-06-25 17:13:37 +00:00
: ( NSString * ) colorSpaceName
: ( const unsigned char * const [ 5 ] ) data
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-09-23 18:04:06 +00:00
NSDebugLLog ( @ "OpalGState" , @ " %s - %@ - cgctx %@" , __PRETTY _FUNCTION __ , _opalSurface , [ self CGContext ] ) ;
2013-07-23 23:18:48 +00:00
// This depends on CGAffineTransform and NSAffineTransformStruct having
// the same in - memory layout .
// Here ' s an elementary check if that is true .
// We should probably check this in - back ' s "configure" script .
assert ( sizeof ( CGAffineTransform ) = = sizeof ( NSAffineTransformStruct ) ) ;
NSAffineTransformStruct nsAT = [ matrix transformStruct ] ;
CGAffineTransform cgAT = * ( CGAffineTransform * ) & nsAT ;
2013-09-23 18:04:06 +00:00
NSDebugLLog ( @ "OpalGState" , @ "tf: %@ x %@" , matrix , [ self GSCurrentCTM ] ) ;
2013-07-21 11:58:05 +00:00
CGContextSaveGState ( CGCTX ) ;
2013-09-23 18:04:06 +00:00
// OPContextSetIdentityCTM ( CGCTX ) ;
2013-07-23 23:18:48 +00:00
CGContextConcatCTM ( CGCTX , cgAT ) ;
2013-09-23 18:04:06 +00:00
// OPContextSetCairoDeviceOffset ( CGCTX , 0 , 0 ) ;
// CGContextMoveToPoint ( CGCTX , 0 , 0 ) ;
# if 0
CGContextSetRGBFillColor ( CGCTX , 1 , 0 , 0 , 1 ) ;
CGContextFillRect ( CGCTX , CGRectMake ( -512 , -512 , 1024 , 1024 / * pixelsWide , pixelsHigh * / ) ) ;
# endif
// CGContextRestoreGState ( CGCTX ) ;
// return ;
2013-08-01 22:28:57 +00:00
// TODO :
// We may want to normalize colorspace names between Opal and - gui ,
// to avoid this conversion ?
NSLog ( @ "Colorspace %@" , colorSpaceName ) ;
if ( [ colorSpaceName isEqualToString : NSCalibratedRGBColorSpace ] )
colorSpaceName = kCGColorSpaceGenericRGB ; // SRGB ?
else if ( [ colorSpaceName isEqualToString : NSDeviceRGBColorSpace ] )
colorSpaceName = kCGColorSpaceGenericRGB ;
// TODO : bitsPerComponent ( in variable bitsPerSample ) is not
// liked combined with bitsBerPixel
else if ( [ colorSpaceName isEqualToString : NSCalibratedWhiteColorSpace ] )
colorSpaceName = kCGColorSpaceGenericGray ;
else if ( [ colorSpaceName isEqualToString : NSDeviceWhiteColorSpace ] )
colorSpaceName = kCGColorSpaceGenericGray ;
else
{
NSLog ( @ "Opal backend: Unhandled colorspace: %@" , colorSpaceName ) ;
CGContextRestoreGState ( CGCTX ) ;
return ;
}
if ( bitsPerPixel ! = 32 )
{
NSLog ( @ "Bits per pixel: %d - the only verified combination is 32" , bitsPerPixel ) ;
CGContextRestoreGState ( CGCTX ) ;
return ;
}
// CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName ( colorSpaceName ) ;
CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName ( kCGColorSpaceGenericRGB ) ;
# if 0
NSData * nsData = [ NSData dataWithBytesNoCopy : * data
length : pixelsHigh * bytesPerRow ] ;
# else
# warning Using suboptimal ' - dataWithBytes : length : ' because NoCopy variant breaks down
NSData * nsData = [ NSData dataWithBytes : * data
length : pixelsHigh * bytesPerRow ] ;
# endif
CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData ( nsData ) ;
NSLog ( @ "Bits per component : bitspersample = %d" , bitsPerSample ) ;
NSLog ( @ "Bits per pixel : bitsperpixel = %d" , bitsPerPixel ) ;
NSLog ( @ " : samplesperpixel = %d" , samplesPerPixel ) ;
CGImageRef img = CGImageCreate ( pixelsWide , pixelsHigh , bitsPerSample ,
bitsPerPixel , bytesPerRow , colorSpace ,
hasAlpha ? kCGImageAlphaPremultipliedLast : 0 / * correct ? * / ,
dataProvider ,
NULL / * const CGFloat decode [ ] is what ? * / ,
false , / * shouldInterpolate ? * /
kCGRenderingIntentDefault ) ;
CGContextDrawImage ( CGCTX , CGRectMake ( 0 , 0 , pixelsWide , pixelsHigh ) , img ) ;
2013-09-23 18:04:06 +00:00
// [ _opalSurface _saveImage : img withPrefix : @ "/tmp/opalback-dpsimage-" size : NSZeroSize ] ;
2013-08-01 22:28:57 +00:00
CGDataProviderRelease ( dataProvider ) ;
CGImageRelease ( img ) ;
2013-07-21 11:58:05 +00:00
CGContextRestoreGState ( CGCTX ) ;
2013-06-25 17:13:37 +00:00
}
- ( void ) compositeGState : ( OpalGState * ) source
fromRect : ( NSRect ) srcRect
toPoint : ( NSPoint ) destPoint
op : ( NSCompositingOperation ) op
fraction : ( CGFloat ) delta
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-09-23 18:04:06 +00:00
CGContextRef destContexts [ 2 ] = { [ _opalSurface backingCGContext ] , [ _opalSurface x11CGContext ] } ;
/ * x11 context needs to have correct ctm applied * /
CGContextSaveGState ( [ _opalSurface x11CGContext ] ) ;
OPContextSetIdentityCTM ( [ _opalSurface x11CGContext ] ) ;
CGContextConcatCTM ( [ _opalSurface x11CGContext ] , CGContextGetCTM ( [ _opalSurface backingCGContext ] ) ) ;
for ( int i = 0 ; i < 1 ; i + + ) // not drawing into x11cgctx after all .
{
CGContextRef ctx = destContexts [ i ] ;
[ self compositeGState : source
fromRect : srcRect
toPoint : destPoint
op : op
fraction : delta
destCGContext : ctx ] ;
}
/ * restore x11 context ' s previous state * /
CGContextRestoreGState ( [ _opalSurface x11CGContext ] ) ;
}
- ( void ) drawGState : ( OpalGState * ) source
fromRect : ( NSRect ) srcRect
toPoint : ( NSPoint ) destPoint
op : ( NSCompositingOperation ) op
fraction : ( CGFloat ) delta
{
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
CGContextRef destContexts [ 2 ] = { [ _opalSurface backingCGContext ] , [ _opalSurface x11CGContext ] } ;
2013-09-23 18:29:40 +00:00
for ( int i = 0 ; i < 1 ; i + + )
2013-09-23 18:04:06 +00:00
{
CGContextRef ctx = destContexts [ i ] ;
[ self drawGState : source
fromRect : srcRect
toPoint : destPoint
op : op
fraction : delta
destCGContext : ctx ] ;
}
}
- ( void ) compositeGState : ( OpalGState * ) source
fromRect : ( NSRect ) srcRect
toPoint : ( NSPoint ) destPoint
op : ( NSCompositingOperation ) op
fraction : ( CGFloat ) delta
destCGContext : ( CGContextRef ) destCGContext
{
// NOTE : This method seems to need to paint to X11 context , too .
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s - from %@ of gstate %p (cgctx %p) to %@ of %p (cgctx %p)" , self , [ self class ] , __PRETTY _FUNCTION __ , NSStringFromRect ( srcRect ) , source , [ source CGContext ] , NSStringFromPoint ( destPoint ) , self , [ self CGContext ] ) ;
2013-09-19 22:39:11 +00:00
# if 0
2013-09-23 18:04:06 +00:00
CGContextSaveGState ( destCGContext ) ;
CGContextSetRGBFillColor ( destCGContext , 1 , 1 , 0 , 1 ) ;
CGContextFillRect ( destCGContext , CGRectMake ( destPoint . x , destPoint . y , srcRect . size . width , srcRect . size . height ) ) ;
CGContextRestoreGState ( destCGContext ) ;
2013-07-21 11:58:05 +00:00
# else
2013-09-23 18:04:06 +00:00
# if 1
NSSize ssize = [ source -> _opalSurface size ] ;
srcRect = [ [ source GSCurrentCTM ] rectInMatrixSpace : srcRect ] ;
destPoint = [ [ self GSCurrentCTM ] pointInMatrixSpace : destPoint ] ;
srcRect . origin . y = ssize . height - srcRect . origin . y - srcRect . size . height ;
2013-07-21 11:58:05 +00:00
2013-09-23 18:04:06 +00:00
CGRect srcCGRect = _CGRectFromNSRect ( srcRect ) ;
CGRect destCGRect = CGRectMake ( destPoint . x , destPoint . y ,
srcRect . size . width , srcRect . size . height ) ;
NSLog ( @ "Source cgctx: %p, self: %p - from %@ to %@ with ctm %@" , [ source CGContext ] , self , _CGRectRepr ( srcCGRect ) , _CGRectRepr ( destCGRect ) , [ self GSCurrentCTM ] ) ;
// FIXME : this presumes that the backing CGContext of ' source ' is
2013-07-21 11:58:05 +00:00
// an OpalSurface with a backing CGBitmapContext
2013-09-23 18:04:06 +00:00
CGImageRef backingImage = CGBitmapContextCreateImage ( [ source CGContext ] ) ;
CGImageRef subImage = CGImageCreateWithImageInRect ( backingImage , srcCGRect ) ;
CGContextSaveGState ( destCGContext ) ;
OPContextSetIdentityCTM ( destCGContext ) ;
OPContextSetCairoDeviceOffset ( destCGContext , 0 , 0 ) ;
// TODO : this ignores op
// TODO : this ignores delta
CGContextDrawImage ( destCGContext , destCGRect , subImage ) ;
OPContextSetCairoDeviceOffset ( CGCTX , - offset . x ,
offset . y - [ _opalSurface device ] -> buffer_height ) ;
CGContextRestoreGState ( destCGContext ) ;
CGImageRelease ( subImage ) ;
CGImageRelease ( backingImage ) ;
# else
CGImageRef src ;
NSSize ssize = NSZeroSize ;
BOOL copyOnSelf ;
/ * The source rect in the source base coordinate space .
This rect is the minimum bounding rect of srcRect . * /
NSRect srcRectInBase = NSZeroRect ;
/ * The destination point in the target base coordinate space * /
NSPoint destPointInBase = NSZeroPoint ;
/ * The origin of srcRectInBase * /
double minx , miny ;
/ * The composited content size * /
double width , height ;
/ * The adjusted destination point in the target base coordinate space * /
double x , y ;
/ * Alternative source rect origin in the source current CTM * /
NSPoint srcRectAltOrigin ;
/ * Alternative source rect origin in the source base coordinate space * /
NSPoint srcRectAltOriginInBase ;
/ * The source rect origin in the source base coordinate space * /
NSPoint srcRectOriginInBase ;
BOOL originFlippedBetweenBaseAndSource = NO ;
/ * The delta between the origins of srcRect and srcRectInBase * /
double dx , dy ;
if ( ! [ source CGContext ] || ! destCGContext )
return ;
src = CGBitmapContextCreateImage ( [ source CGContext ] ) ;
copyOnSelf = ( [ source CGContext ] = = destCGContext ) ;
srcRectAltOrigin = NSMakePoint ( srcRect . origin . x , srcRect . origin . y + srcRect . size . height ) ;
srcRectAltOriginInBase = [ [ source GSCurrentCTM ] transformPoint : srcRectAltOrigin ] ;
srcRectOriginInBase = [ [ source GSCurrentCTM ] transformPoint : srcRect . origin ] ;
CGContextSaveGState ( destCGContext ) ;
/ * When the target and source are the same surface , we use the group tricks * /
/ * // ?
if ( copyOnSelf ) cairo_push _group ( _ct ) ;
cairo_new _path ( _ct ) ;
_set _op ( _ct , op ) ;
* /
/ * Scales and / or rotates the local destination point with the current AppKit CTM * /
destPointInBase = [ ctm transformPoint : destPoint ] ;
/ * Scales and / or rotates the source rect and retrieves the minimum bounding
rectangle that encloses it and makes it our source area * /
[ [ source GSCurrentCTM ] boundingRectFor : srcRect result : & srcRectInBase ] ;
/ * Find whether the source rect origin in the base is the same than in the
source current CTM .
We need to know the origin in the base to compute how much the source
bounding rect origin is shifted relatively to the closest source rect corner .
We use this delta ( dx , dy ) to correctly composite from a rotated source . * /
originFlippedBetweenBaseAndSource =
( ( srcRect . origin . y < srcRectAltOrigin . y && srcRectOriginInBase . y > srcRectAltOriginInBase . y )
|| ( srcRect . origin . y > srcRectAltOrigin . y && srcRectOriginInBase . y < srcRectAltOriginInBase . y ) ) ;
if ( originFlippedBetweenBaseAndSource )
{
srcRectOriginInBase = srcRectAltOriginInBase ;
}
dx = srcRectOriginInBase . x - srcRectInBase . origin . x ;
dy = srcRectOriginInBase . y - srcRectInBase . origin . y ;
if ( source -> _opalSurface ! = nil )
{
ssize = [ source -> _opalSurface size ] ;
}
/ *
// ?
if ( cairo_version ( ) >= CAIRO_VERSION _ENCODE ( 1 , 8 , 0 ) )
{
// For cairo > 1.8 we seem to need this adjustment
srcRectInBase . origin . y - = 2 * ( source -> offset . y - ssize . height ) ;
}
* /
x = destPointInBase . x ;
y = destPointInBase . y ;
minx = NSMinX ( srcRectInBase ) ;
miny = NSMinY ( srcRectInBase ) ;
width = NSWidth ( srcRectInBase ) ;
height = NSHeight ( srcRectInBase ) ;
/ * Comment from cairo backend :
- - - - -8 < - - - - * /
/ * We respect the AppKit CTM effect on the origin ' aPoint ' ( see
- [ ctm transformPoint : ] ) , but we ignore the scaling and rotation effect on
the composited content and size . Which means we never rotate or scale the
content we composite .
We use a pattern as a trick to simulate a target CTM change , this way we
don ' t touch the source CTM even when both source and target are identical
( e . g . scrolling case ) .
We must use a pattern matrix that matches the AppKit base CTM set up in
- DPSinitgraphics to ensure no transform is applied to the source content ,
translation adjustements related to destination point and source rect put
aside . * /
/ * - - - - -8 < - - - -
We don ' t have patterns with their own matrices at our disposal , so the
relevant code is NOT here . Instead we directly use srcRectInBase
* /
NSLog ( @ "dy: %d" , ( int ) dy ) ;
CGRect srcCGRect = CGRectMake ( srcRect . origin . x , srcRect . origin . y , srcRect . size . width , srcRect . size . height ) ;
srcCGRect = CGRectMake ( minx , miny , width , height ) ;
CGImageRef srcSubImage = CGImageCreateWithImageInRect ( src , srcCGRect ) ;
// OPContextSetIdentityCTM ( destCGContext ) ;
// CGContextScaleCTM ( destCGContext , 1 , -1 ) ;
// CGContextTranslateCTM ( destCGContext , - ( minx - x + dx ) , miny - y + dy - ssize . height ) ;
// OPContextResetClip ( destCGContext ) ;
// CGContextAddRect ( destCGContext , CGRectMake ( x , y , width , height ) ) ;
// CGContextClip ( destCGContext ) ;
// TODO : this ignores op
// TODO : this ignores delta
// ( delta = = opacity , in cairo backend )
CGRect destCGRect = CGRectMake ( x , y , width , height ) ;
CGContextDrawImage ( destCGContext , destCGRect , srcSubImage ) ;
CGContextSetRGBFillColor ( destCGContext , 0.6 , 1.0 , 0.2 , 0.2 ) ;
CGContextFillRect ( destCGContext , destCGRect ) ;
// NSLog ( @ " --> compsoiting subimage %@" , srcSubImage ) ;
// [ source -> _opalSurface _saveImage : srcSubImage withPrefix : [ NSString stringWithFormat : @ "/tmp/opalback-compositing-subimage-%p-" , [ source CGContext ] ] size : srcCGRect . size ] ;
// [ source -> _opalSurface _saveImage : src withPrefix : [ NSString stringWithFormat : @ "/tmp/opalback-compositing-image-%p-" , [ source CGContext ] ] size : NSZeroSize ] ;
CGImageRelease ( src ) ;
CGContextRestoreGState ( destCGContext ) ;
# endif
# endif
}
/ * * Unlike - compositeGState , - drawGSstate fully respects the AppKit CTM but
doesn ' t support to use the receiver cairo target as the source . * /
/ * This method is required if - [ OpalContext supportsDrawGState ] returns YES * /
- ( void ) drawGState : ( OpalGState * ) source
fromRect : ( NSRect ) srcRect
toPoint : ( NSPoint ) destPoint
op : ( NSCompositingOperation ) op
fraction : ( CGFloat ) delta
destCGContext : ( CGContextRef ) destCGContext
{
// TODO : CairoGState has a lot more complex implementation .
// For now , we ' ll just call compositeGState and live
// with the fact that CTM is not respected .
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
# if 0
[ self compositeGState : source fromRect : srcRect toPoint : destPoint op : op fraction : delta destCGContext : destCGContext ] ;
# else
CGRect srcCGRect = CGRectMake ( srcRect . origin . x , srcRect . origin . y ,
srcRect . size . width , srcRect . size . height ) ;
CGRect destCGRect = CGRectMake ( destPoint . x , destPoint . y ,
srcRect . size . width , srcRect . size . height ) ;
CGImageRef backingImage = CGBitmapContextCreateImage ( [ source CGContext ] ) ;
CGImageRef subImage = CGImageCreateWithImageInRect ( backingImage , srcCGRect ) ;
2013-07-21 11:58:05 +00:00
// TODO : this ignores op
// TODO : this ignores delta
2013-09-23 18:04:06 +00:00
CGContextDrawImage ( destCGContext , destCGRect , subImage ) ;
CGImageRelease ( subImage ) ;
2013-07-21 11:58:05 +00:00
CGImageRelease ( backingImage ) ;
# endif
2013-06-25 17:13:37 +00:00
}
- ( void ) compositerect : ( NSRect ) aRect
op : ( NSCompositingOperation ) op
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s - %@" , self , [ self class ] , __PRETTY _FUNCTION __ , NSStringFromRect ( aRect ) ) ;
2013-07-15 15:24:04 +00:00
CGContextSaveGState ( CGCTX ) ;
2013-07-21 11:58:05 +00:00
[ self DPSinitmatrix ] ;
CGContextFillRect ( CGCTX , CGRectMake ( aRect . origin . x , [ _opalSurface device ] -> buffer_height - aRect . origin . y ,
2013-07-15 15:24:04 +00:00
aRect . size . width , aRect . size . height ) ) ;
CGContextRestoreGState ( CGCTX ) ;
}
- ( void ) DPSsetdash : ( const CGFloat * ) pat
: ( NSInteger ) size
: ( CGFloat ) offset
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-06-25 17:13:37 +00:00
2013-07-15 15:24:04 +00:00
// TODO : stub
}
- ( void ) DPSstroke
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-07-15 15:24:04 +00:00
CGContextStrokePath ( CGCTX ) ;
2013-07-11 20:44:32 +00:00
}
2013-08-01 22:28:57 +00:00
- ( void ) DPSsetlinejoin : ( int ) linejoin
{
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-09-23 18:04:06 +00:00
CGContextSetLineJoin ( CGCTX , linejoin ) ;
2013-08-01 22:28:57 +00:00
}
- ( void ) DPSsetlinecap : ( int ) linecap
{
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-09-23 18:04:06 +00:00
// TODO : ensure match of linecap constants between Opal and DPS
CGContextSetLineCap ( CGCTX , linecap ) ;
2013-08-01 22:28:57 +00:00
}
- ( void ) DPSsetmiterlimit : ( CGFloat ) miterlimit
{
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-09-23 18:04:06 +00:00
CGContextSetMiterLimit ( CGCTX , miterlimit ) ;
2013-08-01 22:28:57 +00:00
}
2013-07-11 20:44:32 +00:00
@ end
// MARK : Initialization methods
// MARK : -
@ implementation OpalGState ( InitializationMethods )
2013-09-19 22:39:11 +00:00
- ( id ) copyWithZone : ( NSZone * ) zone
{
2013-09-23 18:04:06 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-09-19 22:39:11 +00:00
OpalGState * theCopy = ( OpalGState * ) [ super copyWithZone : zone ] ;
[ _opalSurface retain ] ;
2013-09-23 18:04:06 +00:00
if ( CGCTX )
{
theCopy -> _opGState = OPContextCopyGState ( CGCTX ) ;
}
else
{
// FIXME : perhaps Opal could provide an API for getting the default
// gstate ?
CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName ( kCGColorSpaceGenericRGB ) ;
CGContextRef ctx = CGBitmapContextCreate ( NULL , 1 , 1 , 8 , 32 , colorSpace , kCGImageAlphaPremultipliedFirst ) ;
CGColorSpaceRelease ( colorSpace ) ;
theCopy -> _opGState = OPContextCopyGState ( ctx ) ;
CGContextRelease ( ctx ) ;
NSLog ( @ "Included default gstate %p" , theCopy -> _opGState ) ;
}
2013-09-19 22:39:11 +00:00
return theCopy ;
}
2013-07-11 20:44:32 +00:00
/ * SOME NOTES :
- GState approximates a cairo context : a drawing state .
- Surface approximates a cairo surface : a place to draw things .
- CGContext seems to be a mix of these two : surface + state .
Should we unite these two somehow ? Can we unite these two somehow ?
Possibly not . We still need to support bitmap contexts , pdf contexts
etc which contain both state and contents .
So , we will still need surfaces ( containing CGContexts , hence including
state ) and GState as a wrapper around whatever context happens to be
the current one .
* /
/ * *
Makes the specified surface active in the current graphics state ,
2013-07-21 11:58:05 +00:00
ready for use . Also , sets the device offset to specified coordinates .
2013-07-11 20:44:32 +00:00
* * /
- ( void ) GSSetSurface : ( OpalSurface * ) opalSurface
: ( int ) x
: ( int ) y
{
2013-09-23 18:04:06 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s - %@ %d %d" , self , [ self class ] , __PRETTY _FUNCTION __ , opalSurface , x , y ) ;
2013-07-11 20:44:32 +00:00
2013-07-21 11:58:05 +00:00
if ( _opalSurface ! = opalSurface )
{
id old = _opalSurface ;
_opalSurface = [ opalSurface retain ] ;
[ old release ] ;
}
[ self setOffset : NSMakePoint ( x , y ) ] ;
[ self DPSinitgraphics ] ;
2013-07-11 20:44:32 +00:00
}
2013-07-15 15:24:04 +00:00
- ( id ) GSCurrentSurface : ( OpalSurface * * ) surface
: ( int * ) x
: ( int * ) y
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-07-11 20:44:32 +00:00
2013-07-15 15:24:04 +00:00
return _opalSurface ;
}
2013-07-11 20:44:32 +00:00
/ * *
Sets up a new CG * Context ( ) for drawing content .
* * /
- ( void ) DPSinitgraphics
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-07-11 20:44:32 +00:00
[ super DPSinitgraphics ] ;
2013-09-23 18:04:06 +00:00
if ( ! _opalSurface )
{
NSLog ( @ "%s: called before GSSetSurface:::" , __PRETTY _FUNCTION __ ) ;
return ;
}
// TODO : instead of recreating contexts , we should only reset
// the gstate portion of the contexts . Add OPContextResetGState ( ) which
// recreates _ct and resets _ctadditions . See DPSinitgraphics in
// CairoGState .
2013-07-21 11:58:05 +00:00
[ _opalSurface createCGContexts ] ;
2013-09-23 18:04:06 +00:00
OPContextSetCairoDeviceOffset ( CGCTX , - offset . x ,
offset . y - [ _opalSurface device ] -> buffer_height ) ;
while ( _CGContextSaveGStatesOnContextCreation > 0 )
{
NSLog ( @ "%d more times" , _CGContextSaveGStatesOnContextCreation ) ;
CGContextSaveGState ( CGCTX ) ;
_CGContextSaveGStatesOnContextCreation - - ;
}
2013-07-25 14:49:44 +00:00
/ *
if ( [ _opalSurface device ] )
{
CGContextTranslateCTM ( CGCTX , 0 , [ _opalSurface device ] -> buffer_height ) ;
CGContextScaleCTM ( CGCTX , 1 , -1 ) ;
}
* /
2013-07-11 20:44:32 +00:00
}
@ end
2013-07-15 15:24:04 +00:00
// MARK : Accessors
2013-07-11 20:44:32 +00:00
// MARK : -
2013-07-15 15:24:04 +00:00
@ implementation OpalGState ( Accessors )
2013-07-11 20:44:32 +00:00
2013-09-23 18:04:06 +00:00
- ( CGContextRef ) CGContext
2013-07-15 15:24:04 +00:00
{
2013-07-23 23:18:48 +00:00
if ( ! _opalSurface )
NSDebugMLLog ( @ "OpalGState" , @ "No OpalSurface" ) ;
2013-09-23 18:04:06 +00:00
else if ( ! [ _opalSurface CGContext ] )
2013-07-23 23:18:48 +00:00
NSDebugMLLog ( @ "OpalGState" , @ "No OpalSurface CGContext" ) ;
2013-09-23 18:04:06 +00:00
return [ _opalSurface CGContext ] ;
2013-07-15 15:24:04 +00:00
}
2013-07-11 20:44:32 +00:00
2013-09-19 22:39:11 +00:00
- ( OPGStateRef ) OPGState
{
return _opGState ;
}
- ( void ) setOPGState : ( OPGStateRef ) opGState
{
if ( opGState = = _opGState )
return ;
[ opGState retain ] ;
[ _opGState release ] ;
_opGState = opGState ;
}
2013-07-15 15:24:04 +00:00
@ end
// MARK : Non - required methods
// MARK : -
static CGFloat theAlpha = 1. ; // TODO : removeme
@ implementation OpalGState ( NonrequiredMethods )
- ( void ) DPSsetrgbcolor : ( CGFloat ) r : ( CGFloat ) g : ( CGFloat ) b
2013-07-11 20:44:32 +00:00
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-07-15 15:24:04 +00:00
const CGFloat alpha = 1 ; // TODO : is this correct ?
2013-07-21 11:58:05 +00:00
if ( ! CGCTX )
return ;
2013-07-25 14:49:44 +00:00
CGContextSetRGBStrokeColor ( CGCTX , r , g , b , alpha ) ;
2013-07-15 15:24:04 +00:00
CGContextSetRGBFillColor ( CGCTX , r , g , b , alpha ) ;
2013-07-11 20:44:32 +00:00
}
2013-07-15 15:24:04 +00:00
- ( void ) DPSrectfill : ( CGFloat ) x : ( CGFloat ) y : ( CGFloat ) w : ( CGFloat ) h
2013-07-11 20:44:32 +00:00
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s - rect %g %g %g %g" , self , [ self class ] , __PRETTY _FUNCTION __ , x , y , w , h ) ;
2013-07-21 11:58:05 +00:00
2013-07-15 15:24:04 +00:00
CGContextFillRect ( CGCTX , CGRectMake ( x , y , w , h ) ) ;
2013-07-11 20:44:32 +00:00
}
2013-07-15 15:24:04 +00:00
- ( void ) DPSrectclip : ( CGFloat ) x : ( CGFloat ) y : ( CGFloat ) w : ( CGFloat ) h
2013-07-11 20:44:32 +00:00
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s - %g %g %g %g" , self , [ self class ] , __PRETTY _FUNCTION __ , x , y , w , h ) ;
2013-07-15 15:24:04 +00:00
2013-07-21 11:58:05 +00:00
[ self DPSinitclip ] ;
2013-07-15 15:24:04 +00:00
CGContextClipToRect ( CGCTX , CGRectMake ( x , y , w , h ) ) ;
2013-07-11 20:44:32 +00:00
}
2013-07-15 15:24:04 +00:00
- ( void ) DPSsetgray : ( CGFloat ) gray
2013-07-11 20:44:32 +00:00
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-07-15 15:24:04 +00:00
const CGFloat alpha = 1 ; // TODO : is this correct ?
CGContextSetGrayFillColor ( CGCTX , gray , alpha ) ;
2013-07-11 20:44:32 +00:00
}
- ( void ) DPSsetalpha : ( CGFloat ) a
2013-07-15 15:24:04 +00:00
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s - alpha %g" , self , [ self class ] , __PRETTY _FUNCTION __ , a ) ;
2013-07-15 15:24:04 +00:00
CGContextSetAlpha ( CGCTX , a ) ;
theAlpha = a ;
}
- ( void ) DPSinitmatrix
2013-07-11 20:44:32 +00:00
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-07-15 15:24:04 +00:00
OPContextSetIdentityCTM ( CGCTX ) ;
2013-07-21 11:58:05 +00:00
# if 0
// Flipping the coordinate system is NOT required
CGContextTranslateCTM ( CGCTX , 0 , [ _opalSurface device ] -> buffer_height ) ;
CGContextScaleCTM ( CGCTX , 1 , -1 ) ;
# endif
[ super DPSinitmatrix ] ;
2013-07-11 20:44:32 +00:00
}
2013-07-15 15:24:04 +00:00
- ( void ) DPSconcat : ( const CGFloat * ) m
2013-07-11 20:44:32 +00:00
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s - %g %g %g %g %g %g" , self , [ self class ] , __PRETTY _FUNCTION __ , m [ 0 ] , m [ 1 ] , m [ 2 ] , m [ 3 ] , m [ 4 ] , m [ 5 ] ) ;
2013-07-15 15:24:04 +00:00
CGContextConcatCTM ( CGCTX , CGAffineTransformMake (
m [ 0 ] , m [ 1 ] , m [ 2 ] ,
m [ 3 ] , m [ 4 ] , m [ 5 ] ) ) ;
2013-07-21 11:58:05 +00:00
[ super DPSconcat : m ] ;
2013-07-11 20:44:32 +00:00
}
2013-07-15 15:24:04 +00:00
- ( void ) DPSscale : ( CGFloat ) x
: ( CGFloat ) y
2013-07-11 20:44:32 +00:00
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s - %g %g" , self , [ self class ] , __PRETTY _FUNCTION __ , x , y ) ;
2013-07-15 15:24:04 +00:00
CGContextScaleCTM ( CGCTX , x , y ) ;
2013-07-11 20:44:32 +00:00
}
2013-07-15 15:24:04 +00:00
- ( void ) DPStranslate : ( CGFloat ) x
: ( CGFloat ) y
2013-07-11 20:44:32 +00:00
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s - x %g y %g" , self , [ self class ] , __PRETTY _FUNCTION __ , x , y ) ;
2013-07-15 15:24:04 +00:00
CGContextTranslateCTM ( CGCTX , x , y ) ;
2013-07-21 11:58:05 +00:00
[ super DPStranslate : x : y ] ;
2013-07-11 20:44:32 +00:00
}
2013-07-15 15:24:04 +00:00
- ( void ) DPSmoveto : ( CGFloat ) x
: ( CGFloat ) y
2013-07-11 20:44:32 +00:00
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s - %g %g" , self , [ self class ] , __PRETTY _FUNCTION __ , x , y ) ;
2013-07-15 15:24:04 +00:00
CGContextMoveToPoint ( CGCTX , x , y ) ;
2013-07-11 20:44:32 +00:00
}
2013-07-15 15:24:04 +00:00
- ( void ) DPSlineto : ( CGFloat ) x
: ( CGFloat ) y
2013-07-11 20:44:32 +00:00
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s - %g %g" , self , [ self class ] , __PRETTY _FUNCTION __ , x , y ) ;
2013-07-15 15:24:04 +00:00
CGContextAddLineToPoint ( CGCTX , x , y ) ;
2013-07-11 20:44:32 +00:00
}
2013-07-21 11:58:05 +00:00
- ( void ) setOffset : ( NSPoint ) theOffset
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s - %g %g" , self , [ self class ] , __PRETTY _FUNCTION __ , theOffset . x , theOffset . y ) ;
2013-07-15 15:24:04 +00:00
2013-07-21 11:58:05 +00:00
# if 1
if ( CGCTX ! = nil )
{
# if 1
OPContextSetCairoDeviceOffset ( CGCTX , - theOffset . x ,
theOffset . y - [ _opalSurface device ] -> buffer_height ) ;
# else
OPContextSetCairoDeviceOffset ( CGCTX , theOffset . x ,
theOffset . y ) ;
# endif
}
# else
// This is a BAD hack using transform matrix .
// It ' ll break horribly when Opal state is saved and restored .
static NSPoint OFFSET = { 0 , 0 } ;
// CGContextTranslateCTM ( CGCTX , - ( - OFFSET . x ) ,
// - ( OFFSET . y - [ _opalSurface device ] -> buffer_height ) ) ;
CGContextTranslateCTM ( CGCTX , - theOffset . x ,
theOffset . y - [ _opalSurface device ] -> buffer_height ) ;
OFFSET = theOffset ;
# endif
[ super setOffset : theOffset ] ;
}
2013-07-11 20:44:32 +00:00
/ *
2013-07-15 15:24:04 +00:00
- ( void ) setColor : ( device_color _t * ) color state : ( color_state _t ) cState
2013-07-11 20:44:32 +00:00
{
2013-07-23 23:18:48 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-07-15 15:24:04 +00:00
[ super setColor : color
state : cState ] ;
switch ( color -> space )
{
case rgb_colorspace :
if ( cState & COLOR_STROKE )
CGContextSetRGBStrokeColor ( CGCTX , color -> field [ 0 ] ,
color -> field [ 1 ] , color -> field [ 2 ] , color -> field [ 3 ] ) ;
if ( cState & COLOR_FILL )
CGContextSetRGBFillColor ( CGCTX , color -> field [ 0 ] ,
color -> field [ 1 ] , color -> field [ 2 ] , color -> field [ 3 ] ) ;
break ;
}
2013-07-11 20:44:32 +00:00
}
* /
2013-07-23 23:18:48 +00:00
- ( NSAffineTransform * ) GSCurrentCTM
{
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-09-23 18:04:06 +00:00
return ctm ;
2013-07-23 23:18:48 +00:00
CGAffineTransform cgCTM = CGContextGetCTM ( CGCTX ) ;
NSAffineTransform * affineTransform = [ NSAffineTransform transform ] ;
// This depends on CGAffineTransform and NSAffineTransformStruct having
// the same in - memory layout .
// Here ' s an elementary check if that is true .
// We should probably check this in - back ' s "configure" script .
assert ( sizeof ( CGAffineTransform ) = = sizeof ( NSAffineTransformStruct ) ) ;
NSAffineTransformStruct nsCTM = * ( NSAffineTransformStruct * ) & cgCTM ;
[ affineTransform setTransformStruct : nsCTM ] ;
return affineTransform ;
}
2013-09-23 18:04:06 +00:00
- ( void ) GSSetCTM : ( NSAffineTransform * ) newCTM
{
// This depends on CGAffineTransform and NSAffineTransformStruct having
// the same in - memory layout .
// Here ' s an elementary check if that is true .
// We should probably check this in - back ' s "configure" script .
assert ( sizeof ( CGAffineTransform ) = = sizeof ( NSAffineTransformStruct ) ) ;
NSAffineTransformStruct nsAT = [ newCTM transformStruct ] ;
CGAffineTransform cgAT = * ( CGAffineTransform * ) & nsAT ;
OPContextSetIdentityCTM ( CGCTX ) ;
CGContextConcatCTM ( CGCTX , cgAT ) ;
[ super GSSetCTM : newCTM ] ;
}
2013-07-23 23:18:48 +00:00
- ( void ) flushGraphics
{
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
CGContextFlush ( CGCTX ) ;
2013-09-23 18:04:06 +00:00
[ _opalSurface handleExpose : [ _opalSurface size ] ] ;
2013-07-23 23:18:48 +00:00
}
2013-07-25 14:49:44 +00:00
- ( void ) DPSgsave
{
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-09-23 18:04:06 +00:00
if ( ! CGCTX )
{
if ( _opalSurface )
{
[ _opalSurface createCGContexts ] ;
}
else
{
NSLog ( @ "%s: called before CGContext was created; possible -gui bug?" , __PRETTY _FUNCTION __ ) ;
_CGContextSaveGStatesOnContextCreation + + ;
}
}
CGContextSaveGState ( CGCTX ) ;
2013-07-25 14:49:44 +00:00
}
- ( void ) DPSgrestore
{
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-09-23 18:04:06 +00:00
if ( ! CGCTX )
{
NSLog ( @ "%s: called before CGContext was created; possible -gui bug?" , __PRETTY _FUNCTION __ ) ;
_CGContextSaveGStatesOnContextCreation - - ;
}
CGContextRestoreGState ( CGCTX ) ;
2013-07-25 14:49:44 +00:00
}
- ( void * ) saveClip
{
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
CGRect * r = calloc ( sizeof ( CGRect ) , 1 ) ;
* r = CGContextGetClipBoundingBox ( CGCTX ) ;
return r ;
}
- ( void ) restoreClip : ( void * ) savedClip
{
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
OPContextResetClip ( CGCTX ) ;
CGContextClipToRect ( CGCTX , * ( CGRect * ) savedClip ) ;
free ( savedClip ) ;
}
- ( void ) DPSeoclip
{
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
CGContextEOClip ( CGCTX ) ;
}
- ( void ) DPSeofill
{
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
CGContextEOFillPath ( CGCTX ) ;
}
- ( void ) DPSshow : ( const char * ) s
2013-07-23 23:18:48 +00:00
{
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-07-25 14:49:44 +00:00
2013-07-23 23:18:48 +00:00
CGContextSaveGState ( CGCTX ) ;
2013-07-25 14:49:44 +00:00
CGContextSetRGBFillColor ( CGCTX , 0 , 1 , 0 , 1 ) ;
2013-09-17 19:42:01 +00:00
CGContextFillRect ( CGCTX , CGRectMake ( 0 , 0 , strlen ( s ) * 12 , 12 ) ) ;
2013-07-25 14:49:44 +00:00
CGContextRestoreGState ( CGCTX ) ;
2013-07-23 23:18:48 +00:00
}
2013-07-25 14:49:44 +00:00
- ( void ) GSShowText : ( const char * ) s : ( size_t ) length
2013-07-23 23:18:48 +00:00
{
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-07-25 14:49:44 +00:00
/ *
const char * s2 = calloc ( s , length + 1 ) ;
strcpy ( s2 , s ) ;
* /
CGContextSaveGState ( CGCTX ) ;
CGContextSetRGBFillColor ( CGCTX , 0 , 1 , 0 , 1 ) ;
2013-09-17 19:42:01 +00:00
CGContextFillRect ( CGCTX , CGRectMake ( 0 , 0 , length * 12 , 12 ) ) ;
2013-07-23 23:18:48 +00:00
CGContextRestoreGState ( CGCTX ) ;
2013-07-25 14:49:44 +00:00
// free ( s2 ) ;
}
* Source/opal/OpalFontInfo.m: Move font space to user space conversion
to a separate method. Implement -glyphIsEncoded:, -advancementForGlyph:,
-glyphForCharacter:, -glyphWithName:.
For -boundingRectForGlyph:, and -widthOfString:, return fake, fixed
values.
* Source/opal/OpalContext.m: Fix -isDrawingToScreen implementation;
it now returns YES. This has the unfortunate side effect of breaking
image drawing... but, on the positive side, causes NSLayoutManager
to make calls to GSShowGlyphsWithAdvances in batches of up to
16 glyphs, instead of one at a time...!
* Source/opal/OpalGState.m: Implement -GSSetFont:, and make
-GSShowGlyphsWithAdvances: call CGContextShowGlyphsWithAdvances
Overall state is glyphs are drawn.. they appear upside down,
and the glyph runs only seem to draw at (0, 0).
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@37087 72102866-910b-0410-8b05-ffd578937521
2013-09-17 06:53:08 +00:00
- ( void ) GSSetFont : ( GSFontInfo * ) fontref
{
2013-09-17 21:47:09 +00:00
const CGFloat * matrix ;
* Source/opal/OpalFontInfo.m: Move font space to user space conversion
to a separate method. Implement -glyphIsEncoded:, -advancementForGlyph:,
-glyphForCharacter:, -glyphWithName:.
For -boundingRectForGlyph:, and -widthOfString:, return fake, fixed
values.
* Source/opal/OpalContext.m: Fix -isDrawingToScreen implementation;
it now returns YES. This has the unfortunate side effect of breaking
image drawing... but, on the positive side, causes NSLayoutManager
to make calls to GSShowGlyphsWithAdvances in batches of up to
16 glyphs, instead of one at a time...!
* Source/opal/OpalGState.m: Implement -GSSetFont:, and make
-GSShowGlyphsWithAdvances: call CGContextShowGlyphsWithAdvances
Overall state is glyphs are drawn.. they appear upside down,
and the glyph runs only seem to draw at (0, 0).
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@37087 72102866-910b-0410-8b05-ffd578937521
2013-09-17 06:53:08 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
[ super GSSetFont : fontref ] ;
CGFontRef opalFont = ( CGFontRef ) [ ( ( OpalFontInfo * ) fontref ) -> _faceInfo fontFace ] ;
CGContextSetFont ( CGCTX , opalFont ) ;
2013-09-17 19:42:01 +00:00
CGContextSetFontSize ( CGCTX , 1 ) ;
2013-09-17 21:47:09 +00:00
matrix = [ fontref matrix ] ;
2013-09-17 19:42:01 +00:00
CGAffineTransform cgAT = CGAffineTransformMake ( matrix [ 0 ] , matrix [ 1 ] ,
matrix [ 2 ] , matrix [ 3 ] ,
matrix [ 4 ] , matrix [ 5 ] ) ;
CGContextSetTextMatrix ( CGCTX , cgAT ) ;
* Source/opal/OpalFontInfo.m: Move font space to user space conversion
to a separate method. Implement -glyphIsEncoded:, -advancementForGlyph:,
-glyphForCharacter:, -glyphWithName:.
For -boundingRectForGlyph:, and -widthOfString:, return fake, fixed
values.
* Source/opal/OpalContext.m: Fix -isDrawingToScreen implementation;
it now returns YES. This has the unfortunate side effect of breaking
image drawing... but, on the positive side, causes NSLayoutManager
to make calls to GSShowGlyphsWithAdvances in batches of up to
16 glyphs, instead of one at a time...!
* Source/opal/OpalGState.m: Implement -GSSetFont:, and make
-GSShowGlyphsWithAdvances: call CGContextShowGlyphsWithAdvances
Overall state is glyphs are drawn.. they appear upside down,
and the glyph runs only seem to draw at (0, 0).
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@37087 72102866-910b-0410-8b05-ffd578937521
2013-09-17 06:53:08 +00:00
}
2013-07-25 14:49:44 +00:00
- ( void ) GSShowGlyphsWithAdvances : ( const NSGlyph * ) glyphs : ( const NSSize * ) advances : ( size_t ) length
{
* Source/opal/OpalFontInfo.m: Move font space to user space conversion
to a separate method. Implement -glyphIsEncoded:, -advancementForGlyph:,
-glyphForCharacter:, -glyphWithName:.
For -boundingRectForGlyph:, and -widthOfString:, return fake, fixed
values.
* Source/opal/OpalContext.m: Fix -isDrawingToScreen implementation;
it now returns YES. This has the unfortunate side effect of breaking
image drawing... but, on the positive side, causes NSLayoutManager
to make calls to GSShowGlyphsWithAdvances in batches of up to
16 glyphs, instead of one at a time...!
* Source/opal/OpalGState.m: Implement -GSSetFont:, and make
-GSShowGlyphsWithAdvances: call CGContextShowGlyphsWithAdvances
Overall state is glyphs are drawn.. they appear upside down,
and the glyph runs only seem to draw at (0, 0).
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@37087 72102866-910b-0410-8b05-ffd578937521
2013-09-17 06:53:08 +00:00
size_t i ;
2013-07-25 14:49:44 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
* Source/opal/OpalFontInfo.m: Move font space to user space conversion
to a separate method. Implement -glyphIsEncoded:, -advancementForGlyph:,
-glyphForCharacter:, -glyphWithName:.
For -boundingRectForGlyph:, and -widthOfString:, return fake, fixed
values.
* Source/opal/OpalContext.m: Fix -isDrawingToScreen implementation;
it now returns YES. This has the unfortunate side effect of breaking
image drawing... but, on the positive side, causes NSLayoutManager
to make calls to GSShowGlyphsWithAdvances in batches of up to
16 glyphs, instead of one at a time...!
* Source/opal/OpalGState.m: Implement -GSSetFont:, and make
-GSShowGlyphsWithAdvances: call CGContextShowGlyphsWithAdvances
Overall state is glyphs are drawn.. they appear upside down,
and the glyph runs only seem to draw at (0, 0).
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@37087 72102866-910b-0410-8b05-ffd578937521
2013-09-17 06:53:08 +00:00
// NSGlyph = unsigned int , CGGlyph = unsigned short
CGGlyph cgglyphs [ length ] ;
for ( i = 0 ; i < length ; i + + )
{
cgglyphs [ i ] = glyphs [ i ] ;
}
CGPoint pt = CGContextGetPathCurrentPoint ( CGCTX ) ;
2013-09-17 21:47:09 +00:00
// FIXME : why * 0.66 ?
pt . y + = [ self -> font defaultLineHeightForFont ] * 0.66 ;
* Source/opal/OpalFontInfo.m: Move font space to user space conversion
to a separate method. Implement -glyphIsEncoded:, -advancementForGlyph:,
-glyphForCharacter:, -glyphWithName:.
For -boundingRectForGlyph:, and -widthOfString:, return fake, fixed
values.
* Source/opal/OpalContext.m: Fix -isDrawingToScreen implementation;
it now returns YES. This has the unfortunate side effect of breaking
image drawing... but, on the positive side, causes NSLayoutManager
to make calls to GSShowGlyphsWithAdvances in batches of up to
16 glyphs, instead of one at a time...!
* Source/opal/OpalGState.m: Implement -GSSetFont:, and make
-GSShowGlyphsWithAdvances: call CGContextShowGlyphsWithAdvances
Overall state is glyphs are drawn.. they appear upside down,
and the glyph runs only seem to draw at (0, 0).
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@37087 72102866-910b-0410-8b05-ffd578937521
2013-09-17 06:53:08 +00:00
CGContextSetTextPosition ( CGCTX , pt . x , pt . y ) ;
CGContextShowGlyphsWithAdvances ( CGCTX , cgglyphs , ( const CGSize * ) advances , length ) ;
2013-07-25 14:49:44 +00:00
}
2013-09-17 19:42:01 +00:00
2013-07-25 14:49:44 +00:00
- ( void ) DPSrlineto : ( CGFloat ) x
: ( CGFloat ) y
{
2013-09-16 22:46:45 +00:00
CGFloat x2 , y2 ;
2013-07-25 14:49:44 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s - %g %g" , self , [ self class ] , __PRETTY _FUNCTION __ , x , y ) ;
2013-09-16 22:46:45 +00:00
[ self DPScurrentpoint : & x2 : & y2 ] ;
x2 + = x ;
y2 + = y ;
CGContextAddLineToPoint ( CGCTX , x , y ) ;
2013-07-25 14:49:44 +00:00
}
2013-09-17 19:42:01 +00:00
2013-09-16 22:46:45 +00:00
- ( void ) DPSrmoveto : ( CGFloat ) x
: ( CGFloat ) y
{
CGFloat x2 , y2 ;
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s - %g %g" , self , [ self class ] , __PRETTY _FUNCTION __ , x , y ) ;
[ self DPScurrentpoint : & x2 : & y2 ] ;
x2 + = x ;
y2 + = y ;
CGContextMoveToPoint ( CGCTX , x2 , y2 ) ;
}
2013-09-17 19:42:01 +00:00
2013-07-25 14:49:44 +00:00
- ( void ) DPScurrentpoint : ( CGFloat * ) x
: ( CGFloat * ) y
{
2013-09-16 22:46:45 +00:00
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
2013-07-25 14:49:44 +00:00
CGPoint currentPoint = CGContextGetPathCurrentPoint ( CGCTX ) ;
* x = currentPoint . x ;
* y = currentPoint . y ;
2013-09-16 22:46:45 +00:00
NSDebugLLog ( @ "OpalGState" , @ " %p (%@): %s (returning: %f %f)" , self , [ self class ] , __PRETTY _FUNCTION __ , * x , * y ) ;
2013-07-23 23:18:48 +00:00
}
2013-09-23 18:04:06 +00:00
- ( void ) DPSsetlinewidth : ( CGFloat ) width
{
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
CGContextSetLineWidth ( CGCTX , width ) ;
}
2013-07-15 15:24:04 +00:00
@ end
// MARK : Non - required unimplemented methods
// MARK : -
@ implementation OpalGState ( NonrequiredUnimplementedMethods )
/ *
Methods that follow have not been implemented .
They are here to prevent GSGState implementations from
executing .
Sole criteria for picking them is looking at what methods
are called by a dummy AppKit application with a single
empty NSWindow .
* /
2013-07-25 14:49:44 +00:00
- ( void ) DPSsetgstate : ( NSInteger ) gst
{
NSDebugLLog ( @ "OpalGState" , @ "%p (%@): %s" , self , [ self class ] , __PRETTY _FUNCTION __ ) ;
abort ( ) ;
}
2013-07-15 15:24:04 +00:00
@ end
@ implementation OpalGState ( Unused )
- ( void ) _setPath
{
# if 0
NSInteger count = [ path elementCount ] ;
NSInteger i ;
SEL elmsel = @ selector ( elementAtIndex : associatedPoints : ) ;
NSBezierPathElement (*elmidx)(id, SEL, NSInteger, NSPoint*) =
( NSBezierPathElement (*)(id, SEL, NSInteger, NSPoint*) ) [ path methodForSelector : elmsel ] ;
// reset current cairo path
cairo_new _path ( _ct ) ;
for ( i = 0 ; i < count ; i + + )
{
NSBezierPathElement type ;
NSPoint points [ 3 ] ;
type = ( NSBezierPathElement ) ( * elmidx ) ( path , elmsel , i , points ) ;
switch ( type )
{
case NSMoveToBezierPathElement :
cairo_move _to ( _ct , points [ 0 ] . x , points [ 0 ] . y ) ;
break ;
case NSLineToBezierPathElement :
cairo_line _to ( _ct , points [ 0 ] . x , points [ 0 ] . y ) ;
break ;
case NSCurveToBezierPathElement :
cairo_curve _to ( _ct , points [ 0 ] . x , points [ 0 ] . y ,
points [ 1 ] . x , points [ 1 ] . y ,
points [ 2 ] . x , points [ 2 ] . y ) ;
break ;
case NSClosePathBezierPathElement :
cairo_close _path ( _ct ) ;
break ;
default :
break ;
}
}
# endif
}
2013-06-25 17:13:37 +00:00
@ end