git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.DevExpressVCL@55 05c56307-c608-d34a-929d-697000501d7a
901 lines
31 KiB
ObjectPascal
901 lines
31 KiB
ObjectPascal
{*******************************************************************}
|
|
{ }
|
|
{ Developer Express Visual Component Library }
|
|
{ ExpressPrinting System COMPONENT SUITE }
|
|
{ }
|
|
{ Copyright (C) 1998-2009 Developer Express Inc. }
|
|
{ ALL RIGHTS RESERVED }
|
|
{ }
|
|
{ The entire contents of this file is protected by U.S. and }
|
|
{ International Copyright Laws. Unauthorized reproduction, }
|
|
{ reverse-engineering, and distribution of all or any portion of }
|
|
{ the code contained in this file is strictly prohibited and may }
|
|
{ result in severe civil and criminal penalties and will be }
|
|
{ prosecuted to the maximum extent possible under the law. }
|
|
{ }
|
|
{ RESTRICTIONS }
|
|
{ }
|
|
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
|
|
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
|
|
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
|
|
{ LICENSED TO DISTRIBUTE THE EXPRESSPRINTINGSYSTEM AND }
|
|
{ ALL ACCOMPANYING VCL CONTROLS AS PART OF AN }
|
|
{ EXECUTABLE PROGRAM ONLY. }
|
|
{ }
|
|
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
|
|
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
|
|
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
|
|
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
|
|
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
|
|
{ }
|
|
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
|
|
{ ADDITIONAL RESTRICTIONS. }
|
|
{ }
|
|
{*******************************************************************}
|
|
|
|
unit dxPSPDFMetaFileParser;
|
|
|
|
interface
|
|
|
|
{$I cxVer.inc}
|
|
|
|
uses
|
|
Types, Windows, Classes, SysUtils, Graphics, cxGraphics, dxPSCore, dxBkGnd,
|
|
cxClasses, dxPSPDFExportCore, cxDrawTextUtils, cxGeometry, dxPSPDFExport,
|
|
dxPSGlbl, dxPSFillPatterns, dxPSReportRenderCanvas;
|
|
|
|
type
|
|
|
|
{ TdxPSPDFMetaFileGdiObjectItem }
|
|
|
|
TdxPSPDFMetaFileGdiObjectItem = class(TObject)
|
|
private
|
|
FColor: TColor;
|
|
FHandle: THandle;
|
|
FSourceObject: TObject;
|
|
public
|
|
constructor Create(AHandle: THandle; ASourceObject: TObject; AColor: TColor);
|
|
destructor Destroy; override;
|
|
//
|
|
property Color: TColor read FColor;
|
|
property Handle: THandle read FHandle;
|
|
property SourceObject: TObject read FSourceObject;
|
|
end;
|
|
|
|
{ TdxPSPDFMetaFileGdiObjectList }
|
|
|
|
TdxPSPDFMetaFileGdiObjectList = class(TList)
|
|
private
|
|
function GetItem(Index: Integer): TdxPSPDFMetaFileGdiObjectItem;
|
|
protected
|
|
procedure Notify(Ptr: Pointer; Action: TListNotification); override;
|
|
public
|
|
function CreateBrush(const ABrushInfo: TLogBrush): HBRUSH;
|
|
function CreateFont(const AFontInfo: TExtLogFontW): HFONT;
|
|
function CreatePen(const APenInfo: TLogPen): HPEN;
|
|
function CreatePenEx(const APenInfo: TExtLogPen): HPEN;
|
|
function FindObject(AHandle: THandle; var AObject: TdxPSPDFMetaFileGdiObjectItem): Boolean;
|
|
//
|
|
property Items[Index: Integer]: TdxPSPDFMetaFileGdiObjectItem read GetItem;
|
|
end;
|
|
|
|
{ TdxPSPDFMetaFileExportProvider }
|
|
|
|
TdxPSPDFMetaFileExportProvider = class(TObject)
|
|
private
|
|
FBackgroundColor: TColor;
|
|
FBackgroundMode: Integer;
|
|
FBaseWindowOrg: TPoint;
|
|
FGdiObjectList: TdxPSPDFMetaFileGdiObjectList;
|
|
FInternalWindowOrg: TPoint;
|
|
FMoveToPoint: TPoint;
|
|
FPDFCanvas: TdxPSPDFReportRenderCanvas;
|
|
FPen: TPen;
|
|
FScaleDenumerator: Integer;
|
|
FScaleNumerator: Integer;
|
|
FTextColor: TColor;
|
|
function GetBackgroundColor: TColor;
|
|
function GetPatternColor: TColor;
|
|
procedure SetPen(AValue: TPen);
|
|
protected
|
|
function ConvertPoint(const P: TPoint): TPoint;
|
|
function ConvertPoints(P: Pointer; ACount: Integer; AIsSmallPoints: Boolean): TPointArray;
|
|
function ConvertRect(const R: TRect): TRect;
|
|
function ConvertRegion(ARegion: HRGN): TcxRegion;
|
|
function ConvertValue(AValue: Integer): Integer;
|
|
function CreateRegion(ARgnData: PRgnData; ARgnDataSize: Integer): TcxRegion;
|
|
function ExctractBitmap(ARecordAddress: Pointer;
|
|
ABitmapInfoOffset, ABitmapBitsOffset: Cardinal): TcxBitmap; overload;
|
|
function ExctractBitmap(ARecordAddress: Pointer; const R: TRect;
|
|
ABitmapInfoOffset, ABitmapBitsOffset: Cardinal): TcxBitmap; overload;
|
|
procedure DrawBitmap(const ADest, ASource: TRect; ARecordAddress: Pointer;
|
|
ABitmapInfoOffset, ABitmapBitsOffset: Cardinal);
|
|
//
|
|
procedure EmfAlphaBlend(const ARecord: PEMRAlphaBlend);
|
|
procedure EmfBitBlt(const ARecord: PEMRBitBlt);
|
|
procedure EmfCreateBrush(const ARecord: PEMRCreateBrushIndirect; ATable: PHandleTable);
|
|
procedure EmfCreateFont(const ARecord: PEMRExtCreateFontIndirect; ATable: PHandleTable);
|
|
procedure EmfCreatePen(const ARecord: PEMRCreatePen; ATable: PHandleTable);
|
|
procedure EmfCreatePenEx(const ARecord: PEMRExtCreatePen; ATable: PHandleTable);
|
|
procedure EmfDeleteObject(const ARecord: PEMRSelectObject; ATable: PHandleTable);
|
|
procedure EmfEllipse(R: TRect);
|
|
procedure EmfExcludeClipRect(const ARecord: PEMRExcludeClipRect);
|
|
procedure EmfExtTextOut(const ARecord: PEMRExtTextOut; AIsUnicode: Boolean);
|
|
procedure EmfFillRgn(const ARecord: TEMRFillRgn; ATable: PHandleTable);
|
|
procedure EmfIntersectClipRect(const ARecord: PEMRIntersectClipRect);
|
|
procedure EmfLineTo(const ARecord: TEMRLineTo);
|
|
procedure EmfMaskBlt(const ARecord: PEMRMaskBlt);
|
|
procedure EmfPaintRgn(const ARecord: EMRPaintRgn);
|
|
procedure EmfPie(const ARecord: EMRPie; ATable: PHandleTable);
|
|
procedure EmfPolygon(const APolygon: TEMRPolyline);
|
|
procedure EmfPolygon16(const APolygon: TEMRPolyline16);
|
|
procedure EmfPolyline(const APolyline: TEMRPolyline);
|
|
procedure EmfPolyline16(const APolyline: TEMRPolyline16);
|
|
procedure EmfRectangle(R: TRect);
|
|
procedure EmfRoundRect(R: TRect; ACorners: TSize);
|
|
procedure EmfSelectClipRgn(const ARecord: PEMRExtSelectClipRgn);
|
|
procedure EmfSelectObject(const ARecord: PEMRSelectObject; ATable: PHandleTable);
|
|
procedure EmfSetPixel(const ARecord: TEMRSetPixelV);
|
|
procedure EmfSetWindowOrg(const ARecord: PEMRSetWindowOrgEx);
|
|
procedure EmfStretctBlt(const ARecord: PEMRStretchBlt);
|
|
procedure EmfStretctDIBits(const ARecord: PEMRStretchDIBits);
|
|
procedure WriteMetaFileObject(ATable: PHandleTable;
|
|
AObjectsInTable: Integer; const ARecord: PEnhMetaRecord);
|
|
//
|
|
property BackgroundColor: TColor read GetBackgroundColor;
|
|
property BackgroundMode: Integer read FBackgroundMode;
|
|
property BaseWindowOrg: TPoint read FBaseWindowOrg;
|
|
property GdiObjectList: TdxPSPDFMetaFileGdiObjectList read FGdiObjectList;
|
|
property PatternColor: TColor read GetPatternColor;
|
|
property Pen: TPen read FPen write SetPen;
|
|
property ScaleDenumerator: Integer read FScaleDenumerator;
|
|
property ScaleNumerator: Integer read FScaleNumerator;
|
|
property TextColor: TColor read FTextColor;
|
|
public
|
|
constructor Create(APDFCanvas: TdxPSPDFReportRenderCanvas); virtual;
|
|
destructor Destroy; override;
|
|
procedure Render(AMetaFile: TMetafile; const R: TRect;
|
|
AScaleNumerator, AScaleDenumerator: Integer); virtual;
|
|
//
|
|
property PDFCanvas: TdxPSPDFReportRenderCanvas read FPDFCanvas;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
dxCore;
|
|
|
|
function EnhMetaFileProc(DC: HDC; ATable: PHandleTable;
|
|
const ARecord: PEnhMetaRecord; AObjectsCount: Integer;
|
|
AProvider: TdxPSPDFMetaFileExportProvider): Integer; stdcall;
|
|
begin
|
|
AProvider.WriteMetaFileObject(ATable, AObjectsCount, ARecord);
|
|
Result := 1;
|
|
end;
|
|
|
|
{ TdxPSPDFMetaFileExportProvider }
|
|
|
|
constructor TdxPSPDFMetaFileExportProvider.Create(APDFCanvas: TdxPSPDFReportRenderCanvas);
|
|
begin
|
|
inherited Create;
|
|
FPen := TPen.Create;
|
|
FPDFCanvas := APDFCanvas;
|
|
FGdiObjectList := TdxPSPDFMetaFileGdiObjectList.Create;
|
|
end;
|
|
|
|
destructor TdxPSPDFMetaFileExportProvider.Destroy;
|
|
begin
|
|
FreeAndNil(FPen);
|
|
FreeAndNil(FGdiObjectList);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TdxPSPDFMetaFileExportProvider.ConvertPoint(const P: TPoint): TPoint;
|
|
begin
|
|
Result.X := ConvertValue(P.X);
|
|
Result.Y := ConvertValue(P.Y);
|
|
end;
|
|
|
|
function TdxPSPDFMetaFileExportProvider.ConvertPoints(
|
|
P: Pointer; ACount: Integer; AIsSmallPoints: Boolean): TPointArray;
|
|
const
|
|
OffsetSizeMap: array[Boolean] of Integer = (SizeOf(TPoint), SizeOf(TSmallPoint));
|
|
var
|
|
I: Integer;
|
|
begin
|
|
SetLength(Result, ACount);
|
|
for I := 0 to ACount - 1 do
|
|
begin
|
|
if AIsSmallPoints then
|
|
Result[I] := ConvertPoint(SmallPointToPoint(PSmallPoint(P)^))
|
|
else
|
|
Result[I] := ConvertPoint(PPoint(P)^);
|
|
Inc(Integer(P), OffsetSizeMap[AIsSmallPoints]);
|
|
end;
|
|
end;
|
|
|
|
function TdxPSPDFMetaFileExportProvider.ConvertRect(const R: TRect): TRect;
|
|
begin
|
|
Result.Top := ConvertValue(R.Top);
|
|
Result.Left := ConvertValue(R.Left);
|
|
Result.Right := ConvertValue(R.Right);
|
|
Result.Bottom := ConvertValue(R.Bottom);
|
|
end;
|
|
|
|
function TdxPSPDFMetaFileExportProvider.ConvertRegion(ARegion: HRGN): TcxRegion;
|
|
var
|
|
ARgnData: PRgnData;
|
|
ARgnDataSize: Integer;
|
|
begin
|
|
ARgnDataSize := GetRegionData(ARegion, 0, nil);
|
|
ARgnData := AllocMem(ARgnDataSize);
|
|
try
|
|
if GetRegionData(ARegion, ARgnDataSize, ARgnData) <> 0 then
|
|
Result := CreateRegion(ARgnData, ARgnDataSize)
|
|
else
|
|
Result := nil;
|
|
finally
|
|
FreeMem(ARgnData, ARgnDataSize);
|
|
end;
|
|
end;
|
|
|
|
function TdxPSPDFMetaFileExportProvider.ConvertValue(AValue: Integer): Integer;
|
|
begin
|
|
Result := MulDiv(AValue, ScaleNumerator, ScaleDenumerator);
|
|
end;
|
|
|
|
function TdxPSPDFMetaFileExportProvider.CreateRegion(
|
|
ARgnData: PRgnData; ARgnDataSize: Integer): TcxRegion;
|
|
var
|
|
ARgnRect: PRect;
|
|
I: Integer;
|
|
R: TRect;
|
|
begin
|
|
Result := TcxRegion.Create(cxNullRect);
|
|
ARgnRect := PRect(@ARgnData^.Buffer[0]);
|
|
for I := 0 to ARgnData^.rdh.nCount - 1 do
|
|
begin
|
|
R := ConvertRect(ARgnRect^);
|
|
Result.Combine(TcxRegion.Create(R), roAdd);
|
|
Inc(ARgnRect);
|
|
end;
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfAlphaBlend(const ARecord: PEMRAlphaBlend);
|
|
var
|
|
ASourceBitmap, ABitmap: TcxBitmap;
|
|
R: TRect;
|
|
begin
|
|
ASourceBitmap := ExctractBitmap(ARecord,
|
|
Bounds(ARecord^.xSrc, ARecord^.ySrc, ARecord^.cxSrc, ARecord^.cySrc),
|
|
ARecord^.offBmiSrc, ARecord^.offBitsSrc);
|
|
try
|
|
ABitmap := TcxBitmap.CreateSize(ASourceBitmap.Width, ASourceBitmap.Height);
|
|
try
|
|
ABitmap.cxCanvas.FillRect(ABitmap.ClientRect, ARecord^.crBkColorSrc);
|
|
if cxGetBitmapPixelFormat(ASourceBitmap) = 32 then
|
|
cxAlphaBlend(ABitmap, ASourceBitmap, ABitmap.ClientRect, ASourceBitmap.ClientRect)
|
|
else
|
|
begin
|
|
ASourceBitmap.Transparent := True;
|
|
ABitmap.Canvas.Draw(0, 0, ASourceBitmap);
|
|
end;
|
|
R := Bounds(ARecord^.xDest, ARecord^.yDest, ARecord^.cxDest, ARecord^.cyDest);
|
|
PDFCanvas.DrawPicture(ABitmap, ConvertRect(R), ppmStretch, PixelsNumerator, PixelsDenominator);
|
|
finally
|
|
ABitmap.Free;
|
|
end;
|
|
finally
|
|
ASourceBitmap.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfBitBlt(const ARecord: PEMRBitBlt);
|
|
begin
|
|
if ARecord.cbBitsSrc = 0 then
|
|
begin
|
|
PDFCanvas.FillRect(ConvertRect(
|
|
Bounds(ARecord^.xDest, ARecord^.yDest, ARecord^.cxDest, ARecord^.cyDest)),
|
|
PatternColor);
|
|
end
|
|
else
|
|
DrawBitmap(
|
|
Bounds(ARecord^.xDest, ARecord^.yDest, ARecord^.cxDest, ARecord^.cyDest),
|
|
Bounds(ARecord^.xSrc, ARecord^.ySrc, ARecord^.cxDest, ARecord^.cxDest),
|
|
ARecord, ARecord^.offBmiSrc, ARecord^.offBitsSrc);
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfCreateBrush(
|
|
const ARecord: PEMRCreateBrushIndirect; ATable: PHandleTable);
|
|
begin
|
|
ATable^.objectHandle[ARecord^.ihBrush] := GdiObjectList.CreateBrush(ARecord^.lb);
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfCreateFont(
|
|
const ARecord: PEMRExtCreateFontIndirect; ATable: PHandleTable);
|
|
begin
|
|
ATable^.objectHandle[ARecord^.ihFont] := GdiObjectList.CreateFont(ARecord^.elfw);
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfCreatePen(
|
|
const ARecord: PEMRCreatePen; ATable: PHandleTable);
|
|
begin
|
|
ATable^.objectHandle[ARecord^.ihPen] := GdiObjectList.CreatePen(ARecord^.lopn);
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfCreatePenEx(
|
|
const ARecord: PEMRExtCreatePen; ATable: PHandleTable);
|
|
begin
|
|
ATable^.objectHandle[ARecord^.ihPen] := GdiObjectList.CreatePenEx(ARecord^.elp);
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfDeleteObject(
|
|
const ARecord: PEMRSelectObject; ATable: PHandleTable);
|
|
var
|
|
AObject: TdxPSPDFMetaFileGdiObjectItem;
|
|
begin
|
|
if GdiObjectList.FindObject(ATable^.ObjectHandle[ARecord^.ihObject], AObject) then
|
|
GdiObjectList.Remove(AObject);
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfExtTextOut(
|
|
const ARecord: PEMRExtTextOut; AIsUnicode: Boolean);
|
|
|
|
function CalculateTextWidth(const ARecord: PEMRExtTextOut; const ATextInfo: TEMRText): Integer;
|
|
var
|
|
AOffsets: PInteger;
|
|
I: Integer;
|
|
begin
|
|
Result := 0;
|
|
if ATextInfo.offDx > 0 then
|
|
begin
|
|
AOffsets := PInteger(DWORD(ARecord) + ATextInfo.offDx);
|
|
for I := 0 to ATextInfo.nChars - 1 do
|
|
begin
|
|
Inc(Result, AOffsets^);
|
|
Inc(AOffsets);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function CalculateTextRect(const ARecord: PEMRExtTextOut; const ATextInfo: TEMRText): TRect;
|
|
begin
|
|
Result := ARecord^.rclBounds;
|
|
if (Result.Right < 0) and (Result.Bottom < 0) then
|
|
begin
|
|
Result := Bounds(0, 0, CalculateTextWidth(ARecord, ATextInfo), Abs(PDFCanvas.Font.Size));
|
|
Result := cxRectOffset(Result, ATextInfo.ptlReference);
|
|
end;
|
|
Inc(Result.Bottom, Abs(PDFCanvas.Font.Size));
|
|
end;
|
|
|
|
function ExtractText(const ARecord: PEMRExtTextOut; const ATextInfo: TEMRText): WideString;
|
|
var
|
|
ATextA: AnsiString;
|
|
begin
|
|
if AIsUnicode then
|
|
SetString(Result, PWideChar(DWORD(ARecord) + ATextInfo.offString), ATextInfo.nChars)
|
|
else
|
|
begin
|
|
SetString(ATextA, PAnsiChar(DWORD(ARecord) + ATextInfo.offString), ATextInfo.nChars);
|
|
Result := dxAnsiStringToWideString(ATextA,
|
|
dxGetCodePageFromCharset(PDFCanvas.Font.Charset));
|
|
end;
|
|
end;
|
|
|
|
var
|
|
ATextInfo: TEMRText;
|
|
R: TRect;
|
|
begin
|
|
if ARecord^.emrtext.nChars > 0 then
|
|
begin
|
|
ATextInfo := ARecord^.emrtext;
|
|
R := cxRectOffset(ConvertRect(CalculateTextRect(ARecord, ATextInfo)), FInternalWindowOrg);
|
|
PDFCanvas.DrawTextLine(R, R, cxRectWidth(R), ExtractText(ARecord, ATextInfo), TextColor);
|
|
end;
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfEllipse(R: TRect);
|
|
begin
|
|
R := ConvertRect(R);
|
|
if BackgroundColor <> clNone then
|
|
PDFCanvas.FillEllipse(R, BackgroundColor, TextColor, TdxPSSolidFillPattern, nil);
|
|
PDFCanvas.DrawEllipseFrame(R, Pen.Color, ConvertValue(Pen.Width));
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfFillRgn(
|
|
const ARecord: TEMRFillRgn; ATable: PHandleTable);
|
|
var
|
|
AObject: TdxPSPDFMetaFileGdiObjectItem;
|
|
ARegion: TcxRegion;
|
|
begin
|
|
if GdiObjectList.FindObject(ATable^.ObjectHandle[ARecord.ihBrush], AObject) then
|
|
begin
|
|
ARegion := CreateRegion(@ARecord.RgnData[0], ARecord.cbRgnData);
|
|
try
|
|
PDFCanvas.FillRegion(ARegion.Handle, AObject.Color, clNone, TdxPSSolidFillPattern, nil);
|
|
finally
|
|
ARegion.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfExcludeClipRect(
|
|
const ARecord: PEMRExcludeClipRect);
|
|
begin
|
|
PDFCanvas.ExcludeClipRect(ConvertRect(ARecord^.rclClip));
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfIntersectClipRect(
|
|
const ARecord: PEMRIntersectClipRect);
|
|
begin
|
|
PDFCanvas.IntersectClipRgn(ConvertRect(ARecord^.rclClip));
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfLineTo(const ARecord: TEMRLineTo);
|
|
begin
|
|
PDFCanvas.Polyline(
|
|
[ConvertPoint(FMoveToPoint), ConvertPoint(ARecord.ptl)],
|
|
Pen.Color, ConvertValue(Pen.Width));
|
|
FMoveToPoint := ARecord.ptl;
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfMaskBlt(const ARecord: PEMRMaskBlt);
|
|
|
|
function CreateMaskRegion(const AMaskSourceRect: TRect): TcxRegion;
|
|
var
|
|
AMaskBitmap: TcxBitmap;
|
|
ARegion: HRGN;
|
|
begin
|
|
AMaskBitmap := ExctractBitmap(ARecord, AMaskSourceRect, ARecord^.offBmiMask, ARecord^.offBitsMask);
|
|
try
|
|
ARegion := cxCreateRegionFromBitmap(AMaskBitmap, clWhite);
|
|
Result := ConvertRegion(ARegion);
|
|
DeleteObject(ARegion);
|
|
finally
|
|
AMaskBitmap.Free;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
AMaskRegion: TcxRegion;
|
|
begin
|
|
PDFCanvas.SaveClipRgn;
|
|
try
|
|
AMaskRegion := CreateMaskRegion(
|
|
Bounds(ARecord^.xMask, ARecord^.yMask, ARecord^.cxDest, ARecord^.cyDest));
|
|
if Assigned(AMaskRegion) then
|
|
begin
|
|
AMaskRegion.Offset(ConvertPoint(Point(ARecord^.xDest, ARecord^.yDest)));
|
|
AMaskRegion.Offset(cxPointInvert(PDFCanvas.WindowOrg));
|
|
PDFCanvas.Region.Combine(AMaskRegion, roIntersect);
|
|
end;
|
|
DrawBitmap(
|
|
Bounds(ARecord^.xDest, ARecord^.yDest, ARecord^.cxDest, ARecord^.cyDest),
|
|
cxInvalidRect, ARecord, ARecord^.offBmiSrc, ARecord^.offBitsSrc);
|
|
finally
|
|
PDFCanvas.RestoreClipRgn;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfPaintRgn(const ARecord: EMRPaintRgn);
|
|
var
|
|
ARegion: TcxRegion;
|
|
begin
|
|
if BackgroundColor <> clNone then
|
|
begin
|
|
ARegion := CreateRegion(@ARecord.RgnData[0], ARecord.cbRgnData);
|
|
try
|
|
PDFCanvas.FillRegion(ARegion.Handle, BackgroundColor, clNone,
|
|
TdxPSSolidFillPattern, nil);
|
|
finally
|
|
ARegion.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfPolyline(const APolyline: TEMRPolyline);
|
|
begin
|
|
PDFCanvas.Polyline(
|
|
ConvertPoints(@APolyLine.aptl[0], APolyLine.cptl, False),
|
|
Pen.Color, ConvertValue(Pen.Width));
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfPolyline16(const APolyline: TEMRPolyline16);
|
|
begin
|
|
PDFCanvas.Polyline(
|
|
ConvertPoints(@APolyLine.apts[0], APolyLine.cpts, True),
|
|
Pen.Color, ConvertValue(Pen.Width));
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfPie(
|
|
const ARecord: EMRPie; ATable: PHandleTable);
|
|
begin
|
|
PDFCanvas.Pie(ConvertRect(ARecord.rclBox),
|
|
ConvertPoint(ARecord.ptlStart), ConvertPoint(ARecord.ptlEnd));
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfPolygon(const APolygon: TEMRPolyline);
|
|
begin
|
|
PDFCanvas.Polygon(
|
|
ConvertPoints(@APolygon.aptl[0], APolygon.cptl, True),
|
|
Pen.Color, BackgroundColor, ConvertValue(Pen.Width));
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfPolygon16(const APolygon: TEMRPolyline16);
|
|
begin
|
|
PDFCanvas.Polygon(
|
|
ConvertPoints(@APolygon.apts[0], APolygon.cpts, True),
|
|
Pen.Color, BackgroundColor, ConvertValue(Pen.Width));
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfRectangle(R: TRect);
|
|
begin
|
|
R := ConvertRect(R);
|
|
if BackgroundColor <> clNone then
|
|
PDFCanvas.FillRect(R, BackgroundColor);
|
|
if BackgroundColor <> Pen.Color then
|
|
PDFCanvas.DrawFrame(R, Pen.Color, Pen.Color, ConvertValue(Pen.Width));
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfRoundRect(R: TRect; ACorners: TSize);
|
|
begin
|
|
R := ConvertRect(R);
|
|
ACorners.cx := ConvertValue(ACorners.cx div 2);
|
|
ACorners.cy := ConvertValue(ACorners.cy div 2);
|
|
if BackgroundColor <> clNone then
|
|
begin
|
|
PDFCanvas.FillRoundRect(R, ACorners.cx, ACorners.cy, BackgroundColor,
|
|
TextColor, TdxPSSolidFillPattern, nil);
|
|
end;
|
|
PDFCanvas.DrawRoundFrame(R, ACorners.cx, ACorners.cy,
|
|
Pen.Color, ConvertValue(Pen.Width));
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfSelectClipRgn(
|
|
const ARecord: PEMRExtSelectClipRgn);
|
|
var
|
|
ARegion: TcxRegion;
|
|
begin
|
|
if ARecord.cbRgnData = 0 then
|
|
PDFCanvas.ResetPageRegion
|
|
else
|
|
begin
|
|
ARegion := CreateRegion(@ARecord.RgnData[0], ARecord.cbRgnData);
|
|
ARegion.Offset(cxPointInvert(BaseWindowOrg));
|
|
PDFCanvas.Region.Combine(ARegion, roSet);
|
|
end;
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfSelectObject(
|
|
const ARecord: PEMRSelectObject; ATable: PHandleTable);
|
|
var
|
|
AObject: TdxPSPDFMetaFileGdiObjectItem;
|
|
begin
|
|
if GdiObjectList.FindObject(ATable^.ObjectHandle[ARecord^.ihObject], AObject) then
|
|
begin
|
|
if AObject.SourceObject is TBrush then
|
|
PDFCanvas.Brush := TBrush(AObject.SourceObject);
|
|
if AObject.SourceObject is TPen then
|
|
Pen := TPen(AObject.SourceObject);
|
|
if AObject.SourceObject is TFont then
|
|
begin
|
|
PDFCanvas.Font := TFont(AObject.SourceObject);
|
|
PDFCanvas.Font.Size := ConvertValue(PDFCanvas.Font.Size);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfSetPixel(const ARecord: TEMRSetPixelV);
|
|
var
|
|
R: TRect;
|
|
begin
|
|
R := Rect(ARecord.ptlPixel.X, ARecord.ptlPixel.Y,
|
|
ARecord.ptlPixel.X + 1, ARecord.ptlPixel.Y + 1);
|
|
PDFCanvas.FillRect(ConvertRect(R), ARecord.crColor);
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfSetWindowOrg(const ARecord: PEMRSetWindowOrgEx);
|
|
var
|
|
P: TPoint;
|
|
begin
|
|
P := ConvertPoint(ARecord^.ptlOrigin);
|
|
FInternalWindowOrg := P;
|
|
Inc(P.X, BaseWindowOrg.X);
|
|
Inc(P.Y, BaseWindowOrg.Y);
|
|
PDFCanvas.WindowOrg := P;
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfStretctBlt(const ARecord: PEMRStretchBlt);
|
|
begin
|
|
if ARecord^.cbBitsSrc <> 0 then
|
|
begin
|
|
DrawBitmap(
|
|
Bounds(ARecord^.xDest, ARecord^.yDest, ARecord^.cxDest, ARecord^.cyDest),
|
|
Bounds(ARecord^.xSrc, ARecord^.ySrc, ARecord^.cxSrc, ARecord^.cySrc),
|
|
ARecord, ARecord^.offBmiSrc, ARecord^.offBitsSrc);
|
|
end;
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.EmfStretctDIBits(const ARecord: PEMRStretchDIBits);
|
|
begin
|
|
if ARecord^.cbBitsSrc <> 0 then
|
|
begin
|
|
DrawBitmap(
|
|
Bounds(ARecord^.xDest, ARecord^.yDest, ARecord^.cxDest, ARecord^.cyDest),
|
|
Bounds(ARecord^.xSrc, ARecord^.ySrc, ARecord^.cxSrc, ARecord^.cySrc),
|
|
ARecord, ARecord^.offBmiSrc, ARecord^.offBitsSrc);
|
|
end;
|
|
end;
|
|
|
|
function TdxPSPDFMetaFileExportProvider.ExctractBitmap(
|
|
ARecordAddress: Pointer; ABitmapInfoOffset, ABitmapBitsOffset: Cardinal): TcxBitmap;
|
|
|
|
function GetBitmapBitsSize(const AInfo: TBitmapInfo): Integer;
|
|
begin
|
|
with AInfo.bmiHeader do
|
|
Result := biWidth * Abs(biHeight) * biBitCount div 8;
|
|
end;
|
|
|
|
var
|
|
ABits: Pointer;
|
|
AInfo: PBitmapInfo;
|
|
begin
|
|
Result := TcxBitmap.Create;
|
|
AInfo := PBitmapInfo(DWORD(ARecordAddress) + ABitmapInfoOffset);
|
|
Result.Handle := CreateDIBSection(cxScreenCanvas.Handle, AInfo^, DIB_RGB_COLORS, ABits, 0, 0);
|
|
cxCopyData(Pointer(DWORD(ARecordAddress) + ABitmapBitsOffset), ABits, GetBitmapBitsSize(AInfo^));
|
|
end;
|
|
|
|
function TdxPSPDFMetaFileExportProvider.ExctractBitmap(
|
|
ARecordAddress: Pointer; const R: TRect;
|
|
ABitmapInfoOffset, ABitmapBitsOffset: Cardinal): TcxBitmap;
|
|
var
|
|
ATempBitmap: TcxBitmap;
|
|
begin
|
|
if cxRectIsEqual(R, cxInvalidRect) then
|
|
Result := ExctractBitmap(ARecordAddress, ABitmapInfoOffset, ABitmapBitsOffset)
|
|
else
|
|
begin
|
|
Result := TcxBitmap.CreateSize(R);
|
|
ATempBitmap := ExctractBitmap(ARecordAddress, ABitmapInfoOffset, ABitmapBitsOffset);
|
|
try
|
|
Result.CopyBitmap(ATempBitmap, Result.ClientRect, R.TopLeft);
|
|
finally
|
|
ATempBitmap.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.DrawBitmap(
|
|
const ADest, ASource: TRect; ARecordAddress: Pointer;
|
|
ABitmapInfoOffset, ABitmapBitsOffset: Cardinal);
|
|
var
|
|
ABitmap: TcxBitmap;
|
|
begin
|
|
ABitmap := ExctractBitmap(ARecordAddress, ASource, ABitmapInfoOffset, ABitmapBitsOffset);
|
|
try
|
|
PDFCanvas.DrawPicture(ABitmap, ConvertRect(ADest),
|
|
ppmStretch, PixelsNumerator, PixelsDenominator)
|
|
finally
|
|
ABitmap.Free;
|
|
end;
|
|
end;
|
|
|
|
function TdxPSPDFMetaFileExportProvider.GetBackgroundColor: TColor;
|
|
begin
|
|
if BackgroundMode = TRANSPARENT then
|
|
Result := clNone
|
|
else
|
|
Result := PDFCanvas.Brush.Color;
|
|
end;
|
|
|
|
function TdxPSPDFMetaFileExportProvider.GetPatternColor: TColor;
|
|
begin
|
|
Result := BackgroundColor;
|
|
if Result = clNone then
|
|
Result := TextColor;
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.SetPen(AValue: TPen);
|
|
begin
|
|
FPen.Assign(AValue);
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.Render(AMetaFile: TMetafile;
|
|
const R: TRect; AScaleNumerator, AScaleDenumerator: Integer);
|
|
var
|
|
ASavedWindowOrg: TPoint;
|
|
begin
|
|
PDFCanvas.SaveState;
|
|
ASavedWindowOrg := PDFCanvas.WindowOrg;
|
|
try
|
|
FBaseWindowOrg := Point(R.Left + ASavedWindowOrg.X, R.Top + ASavedWindowOrg.Y);
|
|
FScaleNumerator := AScaleNumerator;
|
|
FScaleDenumerator := AScaleDenumerator;
|
|
PDFCanvas.WindowOrg := FBaseWindowOrg;
|
|
EnumEnhMetaFile(0, AMetaFile.Handle, @EnhMetaFileProc, Self,
|
|
Bounds(0, 0, AMetaFile.Width, AMetaFile.Height));
|
|
finally
|
|
PDFCanvas.WindowOrg := ASavedWindowOrg;
|
|
PDFCanvas.RestoreState;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileExportProvider.WriteMetaFileObject(
|
|
ATable: PHandleTable; AObjectsInTable: Integer; const ARecord: PEnhMetaRecord);
|
|
begin
|
|
case ARecord^.iType of
|
|
EMR_SAVEDC:
|
|
PDFCanvas.SaveState;
|
|
EMR_RESTOREDC:
|
|
PDFCanvas.RestoreState;
|
|
EMR_MASKBLT:
|
|
EmfMaskBlt(PEMRMaskBlt(ARecord));
|
|
EMR_BITBLT:
|
|
EmfBitBlt(PEMRBitBlt(ARecord));
|
|
EMR_STRETCHBLT:
|
|
EmfStretctBlt(PEMRStretchBlt(ARecord));
|
|
EMR_STRETCHDIBITS:
|
|
EmfStretctDIBits(PEMRStretchDiBits(ARecord));
|
|
EMR_ELLIPSE:
|
|
EmfEllipse(PEMREllipse(ARecord)^.rclBox);
|
|
EMR_RECTANGLE:
|
|
EmfRectangle(PEMRRectangle(ARecord)^.rclBox);
|
|
EMR_POLYLINE:
|
|
EmfPolyLine(PEMRPolyline(ARecord)^);
|
|
EMR_POLYLINE16:
|
|
EmfPolyLine16(PEMRPolyline16(ARecord)^);
|
|
EMR_CREATEPEN:
|
|
EmfCreatePen(PEMRCreatePen(ARecord), ATable);
|
|
EMR_SETBKMODE:
|
|
FBackgroundMode := PEMRSETBKMODE(ARecord)^.iMode;
|
|
EMR_EXTSELECTCLIPRGN:
|
|
EmfSelectClipRgn(PEMRExtSelectClipRgn(ARecord));
|
|
EMR_SELECTOBJECT:
|
|
EmfSelectObject(PEMRSelectObject(ARecord), ATable);
|
|
EMR_DELETEOBJECT:
|
|
EmfDeleteObject(PEMRDeleteObject(ARecord), ATable);
|
|
EMR_SETBKCOLOR:
|
|
FBackgroundColor := PEMRSETBKCOLOR(ARecord)^.crColor;
|
|
EMR_SETTEXTCOLOR:
|
|
FTextColor := PEMRSETTEXTCOLOR(ARecord)^.crColor;
|
|
EMR_SETWINDOWORGEX:
|
|
EmfSetWindowOrg(PEMRSETWINDOWORGEX(ARecord));
|
|
EMR_EXCLUDECLIPRECT:
|
|
EmfExcludeClipRect(PEMREXCLUDECLIPRECT(ARecord));
|
|
EMR_INTERSECTCLIPRECT:
|
|
EmfIntersectClipRect(PEMRINTERSECTCLIPRECT(ARecord));
|
|
EMR_CREATEBRUSHINDIRECT:
|
|
EmfCreateBrush(PEMRCreateBrushIndirect(ARecord), ATable);
|
|
EMR_EXTCREATEFONTINDIRECTW:
|
|
EmfCreateFont(PEMRExtCreateFontIndirect(ARecord), ATable);
|
|
EMR_EXTCREATEPEN:
|
|
EmfCreatePenEx(PEMRExtCreatePen(ARecord), ATable);
|
|
EMR_EXTTEXTOUTW, EMR_EXTTEXTOUTA:
|
|
EmfExtTextOut(PEMRExtTextOut(ARecord), ARecord^.iType = EMR_EXTTEXTOUTW);
|
|
EMR_ROUNDRECT:
|
|
EmfRoundRect(PEMRRoundRect(ARecord)^.rclBox, PEMRRoundRect(ARecord)^.szlCorner);
|
|
EMR_POLYGON:
|
|
EmfPolygon(PEMRPolyline(ARecord)^);
|
|
EMR_POLYGON16:
|
|
EmfPolygon16(PEMRPolyline16(ARecord)^);
|
|
EMR_SETPIXELV:
|
|
EmfSetPixel(PEMRSetPixelV(ARecord)^);
|
|
EMR_MOVETOEX:
|
|
FMoveToPoint := PEMRMoveToEx(ARecord)^.ptl;
|
|
EMR_LINETO:
|
|
EmfLineTo(PEMRLineTo(ARecord)^);
|
|
EMR_PAINTRGN:
|
|
EmfPaintRgn(PEMRPaintRgn(ARecord)^);
|
|
EMR_FILLRGN:
|
|
EmfFillRgn(PEMRFillRgn(ARecord)^, ATable);
|
|
EMR_PIE:
|
|
EmfPie(PEMRPie(ARecord)^, ATable);
|
|
EMR_OFFSETCLIPRGN:
|
|
with ConvertPoint(PEMROffsetClipRgn(ARecord)^.ptlOffset) do
|
|
PDFCanvas.Region.Offset(X, Y);
|
|
EMR_ALPHABLEND:
|
|
EmfAlphaBlend(PEMRAlphaBlend(ARecord));
|
|
end;
|
|
end;
|
|
|
|
{ TdxPSPDFMetaFileGdiObjectList }
|
|
|
|
function TdxPSPDFMetaFileGdiObjectList.CreateBrush(const ABrushInfo: TLogBrush): HBRUSH;
|
|
var
|
|
ABrush: TBrush;
|
|
begin
|
|
ABrush := TBrush.Create;
|
|
ABrush.Handle := CreateBrushIndirect(ABrushInfo);
|
|
Add(TdxPSPDFMetaFileGdiObjectItem.Create(ABrush.Handle, ABrush, ABrushInfo.lbColor));
|
|
Result := ABrush.Handle;
|
|
end;
|
|
|
|
function TdxPSPDFMetaFileGdiObjectList.CreateFont(const AFontInfo: EXTLOGFONTW): HFONT;
|
|
var
|
|
AFont: TFont;
|
|
begin
|
|
AFont := TFont.Create;
|
|
AFont.Handle := CreateFontIndirectW(AFontInfo.elfLogFont);
|
|
Add(TdxPSPDFMetaFileGdiObjectItem.Create(AFont.Handle, AFont, clDefault));
|
|
Result := AFont.Handle;
|
|
end;
|
|
|
|
function TdxPSPDFMetaFileGdiObjectList.CreatePen(const APenInfo: TLogPen): HPEN;
|
|
var
|
|
APen: TPen;
|
|
begin
|
|
APen := TPen.Create;
|
|
APen.Color := APenInfo.lopnColor;
|
|
APen.Width := APenInfo.lopnWidth.X;
|
|
Add(TdxPSPDFMetaFileGdiObjectItem.Create(APen.Handle, APen, APenInfo.lopnColor));
|
|
Result := APen.Handle;
|
|
end;
|
|
|
|
function TdxPSPDFMetaFileGdiObjectList.CreatePenEx(const APenInfo: TExtLogPen): HPEN;
|
|
var
|
|
ABrushInfo: TLogBrush;
|
|
APen: TPen;
|
|
begin
|
|
APen := TPen.Create;
|
|
ZeroMemory(@ABrushInfo, SizeOf(ABrushInfo));
|
|
ABrushInfo.lbStyle := APenInfo.elpBrushStyle;
|
|
ABrushInfo.lbColor := APenInfo.elpColor;
|
|
ABrushInfo.lbHatch := APenInfo.elpHatch;
|
|
APen.Handle := ExtCreatePen(APenInfo.elpPenStyle, APenInfo.elpWidth,
|
|
ABrushInfo, APenInfo.elpNumEntries, @APenInfo.elpStyleEntry[0]);
|
|
Add(TdxPSPDFMetaFileGdiObjectItem.Create(APen.Handle, APen, APenInfo.elpColor));
|
|
Result := APen.Handle;
|
|
end;
|
|
|
|
function TdxPSPDFMetaFileGdiObjectList.FindObject(
|
|
AHandle: THandle; var AObject: TdxPSPDFMetaFileGdiObjectItem): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
AObject := nil;
|
|
for I := 0 to Count - 1 do
|
|
begin
|
|
Result := Items[I].Handle = AHandle;
|
|
if Result then
|
|
begin
|
|
AObject := Items[I];
|
|
Break;
|
|
end;
|
|
end;
|
|
Result := Assigned(AObject);
|
|
end;
|
|
|
|
function TdxPSPDFMetaFileGdiObjectList.GetItem(
|
|
Index: Integer): TdxPSPDFMetaFileGdiObjectItem;
|
|
begin
|
|
Result := TdxPSPDFMetaFileGdiObjectItem(inherited Items[Index]);
|
|
end;
|
|
|
|
procedure TdxPSPDFMetaFileGdiObjectList.Notify(Ptr: Pointer; Action: TListNotification);
|
|
begin
|
|
inherited Notify(Ptr, Action);
|
|
if Assigned(Ptr) and (Action = lnDeleted) then
|
|
TObject(Ptr).Free;
|
|
end;
|
|
|
|
{ TdxPSPDFMetaFileGdiObjectItem }
|
|
|
|
constructor TdxPSPDFMetaFileGdiObjectItem.Create(
|
|
AHandle: THandle; ASourceObject: TObject; AColor: TColor);
|
|
begin
|
|
inherited Create;
|
|
FHandle := AHandle;
|
|
FSourceObject := ASourceObject;
|
|
FColor := AColor;
|
|
end;
|
|
|
|
destructor TdxPSPDFMetaFileGdiObjectItem.Destroy;
|
|
begin
|
|
FreeAndNil(FSourceObject);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
end.
|