diff --git a/lcl/interfaces/customdrawn/cocoagdiobjects.pas b/lcl/interfaces/customdrawn/cocoagdiobjects.pas index d0315db915..8349214bf5 100644 --- a/lcl/interfaces/customdrawn/cocoagdiobjects.pas +++ b/lcl/interfaces/customdrawn/cocoagdiobjects.pas @@ -204,6 +204,7 @@ type public ContextSize : TSize; ctx : NSGraphicsContext; + cgctx : CGContextRef; PenPos : TPoint; Stack : Integer; TR,TG,TB : Single; @@ -216,7 +217,7 @@ type procedure Polyline(const Points: array of TPoint; NumPts: Integer); procedure Rectangle(X1, Y1, X2, Y2: Integer; FillRect: Boolean; UseBrush: TCocoaBrush); procedure Ellipse(X1, Y1, X2, Y2: Integer); - procedure TextOut(X,Y: Integer; UTF8Chars: PChar; Count: Integer; CharsDelta: PInteger); + procedure TextOut(X,Y: Integer; UTF8Chars: PChar; Count: Integer; CharsDelta: PInteger; BackgroundAlpha: Single); function GetTextExtentPoint(AStr: PChar; ACount: Integer; var Size: TSize): Boolean; function GetTextMetrics(var TM: TTextMetric): Boolean; procedure DrawBitmap(X,Y: Integer; ABitmap: TCocoaBitmap); @@ -295,6 +296,7 @@ constructor TCocoaBitmap.Create(AWidth, AHeight, ADepth, ABitsPerPixel: Integer; var HasAlpha: Boolean; BitmapFormat: NSBitmapFormat; + DataPointer: Pointer; begin {$ifdef VerboseBitmaps} DebugLn(Format('[TCocoaBitmap.Create] AWidth=%d AHeight=%d ADepth=%d ABitsPerPixel=%d' @@ -304,7 +306,7 @@ begin SetInfo(AWidth, AHeight, ADepth, ABitsPerPixel, AAlignment, AType); // Copy the image data, if necessary - if (AData = nil) or ACopyData then + if ACopyData then begin System.GetMem(FData, FDataSize); FFreeData := True; @@ -312,11 +314,19 @@ begin System.Move(AData^, FData^, FDataSize) // copy data else FillDWord(FData^, FDataSize shr 2, 0); // clear bitmap + DataPointer := @FData; + end + else if (AData = nil) then + begin + FData := AData; + FFreeData := False; + DataPointer := nil; end else begin FData := AData; FFreeData := False; + DataPointer := @FData; end; HasAlpha := AType in [cbtARGB, cbtRGBA, cbtBGRA]; @@ -330,7 +340,7 @@ begin {$endif} // Create the associated NSImageRep imagerep := NSBitmapImageRep(NSBitmapImageRep.alloc.initWithBitmapDataPlanes_pixelsWide_pixelsHigh__colorSpaceName_bitmapFormat_bytesPerRow_bitsPerPixel( - @FData, // planes, BitmapDataPlanes + DataPointer, // planes, BitmapDataPlanes FWidth, // width, pixelsWide FHeight,// height, PixelsHigh FbitsPerSample,// bitsPerSample, bps @@ -648,7 +658,8 @@ end; function TCocoaContext.CGContext:CGContextRef; begin - Result:=CGContextRef(ctx.graphicsPort); + if ctx = nil then Result := cgctx + else Result:=CGContextRef(ctx.graphicsPort); end; procedure TCocoaContext.SetBitmap(const AValue: TCocoaBitmap); @@ -860,25 +871,36 @@ begin CGContextDrawPath(CGContext, kCGPathFillStroke); end; +// for BackgroundAlpha 1 = opaque 0 = transparent procedure TCocoaContext.TextOut(X,Y:Integer;UTF8Chars:PChar;Count:Integer; - CharsDelta:PInteger); + CharsDelta:PInteger; BackgroundAlpha: Single); var - cg : CGContextRef; + cg: CGContextRef; + ns: NSString; + dic: NSDictionary; begin - {cg:=CGContext; +{ // Text rendering with Cocoa only + ns:=NSStringUtf8(UTF8Chars); +// dic := NSDictionary.dictionary(); + ns.drawAtPoint_withAttributes(GetNSPoint(10, 10), nil); +// dic.release; + ns.release;} + + // Text rendering with Carbon mixed (but it doesn't seam to work because cg returns nil) + cg:=CGContext; if not Assigned(cg) then Exit; CGContextScaleCTM(cg, 1, -1); CGContextTranslateCTM(cg, 0, -ContextSize.cy); - CGContextSetRGBFillColor(cg, TR, TG, TB, 1); + CGContextSetRGBFillColor(cg, TR, TG, TB, BackgroundAlpha); fText.SetText(UTF8Chars, Count); fText.Draw(cg, X, ContextSize.cy-Y, CharsDelta); if Assigned(fBrush) then fBrush.Apply(cg); CGContextTranslateCTM(cg, 0, ContextSize.cy); - CGContextScaleCTM(cg, 1, -1);} + CGContextScaleCTM(cg, 1, -1); end; {------------------------------------------------------------------------------ diff --git a/lcl/interfaces/customdrawn/customdrawnint.pas b/lcl/interfaces/customdrawn/customdrawnint.pas index a432130510..9474b82107 100644 --- a/lcl/interfaces/customdrawn/customdrawnint.pas +++ b/lcl/interfaces/customdrawn/customdrawnint.pas @@ -121,7 +121,6 @@ type pool : NSAutoreleasePool; NSApp : NSApplication; delegate : TCDAppDelegate; - ScreenBitmap: TCocoaBitmap; {$endif} public {$ifdef CD_X11} diff --git a/lcl/interfaces/customdrawn/customdrawnobject.inc b/lcl/interfaces/customdrawn/customdrawnobject.inc index ce431c8858..2919083cd0 100644 --- a/lcl/interfaces/customdrawn/customdrawnobject.inc +++ b/lcl/interfaces/customdrawn/customdrawnobject.inc @@ -34,13 +34,6 @@ begin CDWidgetSet := Self; FTerminating := False; - ScreenBitmapHeight := 100; - ScreenBitmapWidth := 100; - ScreenBitmapRawImage.Description.Init_BPP32_A8R8G8B8_BIO_TTB(ScreenBitmapWidth, ScreenBitmapHeight); - ScreenBitmapRawImage.CreateData(True); - ScreenImage := TLazIntfImage.Create(ScreenBitmapRawImage, True); - ScreenDC := TLazCanvas.Create(ScreenImage); - BackendCreate; end; @@ -56,7 +49,6 @@ begin BackendDestroy; CDWidgetSet := nil; - ScreenDC.Free; inherited Destroy; end; diff --git a/lcl/interfaces/customdrawn/customdrawnobject_cocoa.inc b/lcl/interfaces/customdrawn/customdrawnobject_cocoa.inc index decd8134eb..11fa3467f2 100644 --- a/lcl/interfaces/customdrawn/customdrawnobject_cocoa.inc +++ b/lcl/interfaces/customdrawn/customdrawnobject_cocoa.inc @@ -100,16 +100,45 @@ end; Constructor for the class ------------------------------------------------------------------------------} procedure TCDWidgetSet.BackendCreate; +var + ScreenBitmapContext: CGContextRef; begin { Creates the AutoreleasePool } pool := NSAutoreleasePool(NSAutoreleasePool.alloc).init; { Prepares the Native DC for the ScreenDC } - ScreenBitmap := TCocoaBitmap.Create(ScreenBitmapWidth, ScreenBitmapHeight, - 32, 4, cbaDWord, cbtARGB, ScreenBitmapRawImage.Data); + { NSImage / NSBitmapImageRep are very limited. They simply don't support + drawing to the image representation. You can draw to the NSImage, but + that doesn't modify the raw pixels =( + They also don't support us sending our own buffer. If we do so, then it + will create another buffer internally and never draw to our own buffer. + + So CoreGraphics is the best choice here + + see: http://www.cocoabuilder.com/archive/cocoa/89523-drawing-into-nsbitmapimagerep.html + + CoreGraphics also has problems, it doesn't support non-premultiplied Alpha for example: + + see: http://lists.apple.com/archives/carbon-dev/2006/Jan/msg01055.html + } + ScreenBitmapHeight := 100; + ScreenBitmapWidth := 100; + ScreenBitmapRawImage.Description.Init_BPP32_A8R8G8B8_BIO_TTB(ScreenBitmapWidth, ScreenBitmapHeight); + ScreenBitmapRawImage.CreateData(True); + ScreenBitmapContext := CGBitmapContextCreate( + ScreenBitmapRawImage.Data, + ScreenBitmapWidth, + ScreenBitmapHeight, + 8, + ScreenBitmapWidth * 4, + CGColorSpaceCreateDeviceRGB(), + kCGImageAlphaNoneSkipFirst//,kCGImageAlphaPremultipliedFirst + ); + ScreenImage := TLazIntfImage.Create(ScreenBitmapRawImage, True); + ScreenDC := TLazCanvas.Create(ScreenImage); ScreenDC.NativeDC := PtrInt(TCocoaContext.Create); - TCocoaContext(ScreenDC.NativeDC).ctx := NSGraphicsContext.graphicsContextWithBitmapImageRep(ScreenBitmap.imagerep); + TCocoaContext(ScreenDC.NativeDC).cgctx := ScreenBitmapContext; //NSGraphicsContext.graphicsContextWithBitmapImageRep(ScreenBitmap.imagerep); end; {------------------------------------------------------------------------------ @@ -121,6 +150,11 @@ procedure TCDWidgetSet.BackendDestroy; begin { Releases the AutoreleasePool } pool.release; + + { Release the screen DC and Image} + ScreenDC.Free; + ScreenImage.Free; +// ScreenBitmap.Free; end; {------------------------------------------------------------------------------ diff --git a/lcl/interfaces/customdrawn/customdrawnwinapi_cocoa.inc b/lcl/interfaces/customdrawn/customdrawnwinapi_cocoa.inc index 59950f3f5f..67cdea9da1 100644 --- a/lcl/interfaces/customdrawn/customdrawnwinapi_cocoa.inc +++ b/lcl/interfaces/customdrawn/customdrawnwinapi_cocoa.inc @@ -377,7 +377,7 @@ begin ctx := TCocoaContext(lazdc.NativeDC); // Native TextOut - ctx.TextOut(X,Y, Str, Count, Dx); + ctx.TextOut(0, 0, Str, Count, Dx, 0); // Now blend it into our DC lazdc := TLazCanvas(DC);