{ ********************************************************************* Gnostice eDocEngine Copyright (c) Gnostice Information Technologies Private Limited http://www.gnostice.com ********************************************************************* } { ------------------------------------ } { Editor Options } { ------------------------------------ } { } { Use Tab Character = False } { } { ------------------------------------ } {$I ..\gtExpIntf.inc} {$I ..\gtDefines.inc} {$I ..\gtDocDefines.inc} unit gtRichViewIntf; interface uses Classes, Windows, Forms, {$IFDEF ExpIntfRepLinkEnabled} RichView, RVReport, CRVData, PtblRV, RVTypes, {$ENDIF} gtCstDocEng, gtXportIntf, gtExPDFEng, gtPDFEng, gtUtils3; type {$IFNDEF ExpIntfRepLinkEnabled} TRVPrint = class end; TRVReportHelper = class end; {$ENDIF} {$IFDEF gtDelphiXE2Up} [ComponentPlatformsAttribute(pidWin32 or pidWin64)] {$ENDIF} // Options for export TgtRVOption = (rvgoSaveExternalLinks, // saving external links (to URLs) in PDF rvgoSaveLinksToCheckpoints // saving internal links (to checkpoints) in PDF ); TgtRVOptions = set of TgtRVOption; // Zooming options for internal links (how the destination is displayed) TgtRVLinkZoom = (rvglzPageWidth, // fit the page width rvglzPage // fit the full page ); {$IFDEF ExpIntfRepLinkEnabled} TgtRVCheckpointName = {$IFDEF RichView173Up}TRVUnicodeString{$ELSE}String{$ENDIF}; {$ENDIF} TgtRichViewInterface = class(TgtExportInterface) private FOptions: TgtRVOptions; FLinkZoom: TgtRVLinkZoom; {$IFDEF ExpIntfRepLinkEnabled} {$IFDEF RichView17Up} FFullPageSize: TSize; FDocOffset: TPoint; FCheckpoints, FLinks: TCollection; FOldOnDrawHyperlink: TRVDrawHyperlinkEvent; FOldOnDrawCheckpoint: TRVDrawCheckpointEvent; FOldProcessAfterEachPage: Boolean; procedure DoDrawHyperlink(Sender: TCustomRVPrint; RVData: TCustomRVData; ItemNo: Integer; R: TRect); procedure DoDrawCheckpoint(Sender: TCustomRVPrint; RVData: TCustomRVData; ItemNo: Integer; X, Y: Integer); function FindCheckpoint(const CheckpointName: TgtRVCheckpointName; var PageIndex, Left, Top: Integer): Boolean; procedure SaveLinksToCheckpoints; procedure InitLinkCollections(ARVPrint: TCustomRVPrint); procedure DoneLinkCollections(ARVPrint: TCustomRVPrint); {$ENDIF} {$ENDIF} public constructor Create(AOwner: TComponent); override; procedure RenderDocument(ARVPrint: TRVPrint; IsFormatted: Boolean {$IFDEF RichView17Up}; ScaleToScreenDPI: Boolean{$ENDIF}); overload; procedure RenderDocument(ARVHelper: TRVReportHelper); overload; published {$IFDEF RichView17Up} property Options: TgtRVOptions read FOptions write FOptions default [rvgoSaveExternalLinks, rvgoSaveLinksToCheckpoints]; property LinkZoom: TgtRVLinkZoom read FLinkZoom write FLinkZoom default rvglzPageWidth; {$ENDIF} property Engine; end; implementation {$IFDEF ExpIntfRepLinkEnabled} uses RVScroll, RVFuncs, RVItem, RVStyle, PtRVData; {$ENDIF} { ================================ TgtRichViewInterface ======================== } constructor TgtRichViewInterface.Create(AOwner: TComponent); begin inherited Create(AOwner); {$IFDEF RichView17Up} FOptions := [rvgoSaveExternalLinks, rvgoSaveLinksToCheckpoints]; FLinkZoom := rvglzPageWidth; {$ENDIF} end; {$IF Defined(ExpIntfRepLinkEnabled)} {$IFDEF RichView17Up} type TCheckpointLocation = class(TCollectionItem) public Name: TgtRVCheckpointName; PageIndex, Left, Top: Integer; end; TLinkToCheckpoint = class(TCollectionItem) public CheckpointName: TgtRVCheckpointName; PageIndex: Integer; Area: TRect; end; { ------------------------------------------------------------------------------ } { Event: Occurs when drawing a checkpoint. We add the location of this checkpoint to FCheckpoints collection } procedure TgtRichViewInterface.DoDrawCheckpoint(Sender: TCustomRVPrint; RVData: TCustomRVData; ItemNo, X, Y: Integer); var CheckpointData: TCheckpointData; CPTag: TRVTag; CPName: TgtRVCheckpointName; RE: Boolean; begin if Assigned(FOldOnDrawCheckpoint) then FOldOnDrawCheckpoint(Sender, RVData, ItemNo, X, Y); if FCheckpoints = nil then exit; CheckpointData := RVData.GetItemCheckpoint(ItemNo); RVData.GetCheckpointInfo(CheckpointData, CPTag, CPName, RE); with FCheckpoints.Add as TCheckpointLocation do begin Name := CPName; PageIndex := Engine.CurrentPage; Left := X + FDocOffset.X; Top := Y + FDocOffset.Y; end; end; { ------------------------------------------------------------------------------ } { Returns position of checkpoint with the given name } function TgtRichViewInterface.FindCheckpoint(const CheckpointName : TgtRVCheckpointName; var PageIndex, Left, Top: Integer): Boolean; var i: Integer; Item: TCheckpointLocation; begin for i := 0 to FCheckpoints.Count - 1 do begin Item := TCheckpointLocation(FCheckpoints.Items[i]); if Item.Name = CheckpointName then begin PageIndex := Item.PageIndex; Left := Item.Left; Top := Item.Top; Result := True; exit; end; end; Result := False; end; { ------------------------------------------------------------------------------ } { Saves all links to checkpoints to PDF } procedure TgtRichViewInterface.SaveLinksToCheckpoints; var i, PageIndex, Left, Top: Integer; Item: TLinkToCheckpoint; GotoAction: TgtAnnotGoToAction; LinkAnnot: TgtPDFLinkAnnot; PageWidth, PageHeight: Integer; begin if (FLinks = nil) or not(rvgoSaveLinksToCheckpoints in Options) then exit; PageWidth := FFullPageSize.cx; if LinkZoom = rvglzPageWidth then PageHeight := 1 else PageHeight := FFullPageSize.cy; for i := 0 to FLinks.Count - 1 do begin Item := TLinkToCheckpoint(FLinks.Items[i]); if FindCheckpoint(Item.CheckpointName, PageIndex, Left, Top) then begin (Engine as TgtPDFEngine).SetWorkingPage(Item.PageIndex); LinkAnnot := TgtPDFLinkAnnot.Create; LinkAnnot.Rect := gtRect(Item.Area.Left, Item.Area.Top, Item.Area.Right, Item.Area.Bottom); // LinkAnnot.BorderWidth := 1; GotoAction := TgtAnnotGoToAction.Create; GotoAction.Page := PageIndex; GotoAction.Rect := gtRect(0, Top, PageWidth, Top + PageHeight); GotoAction.Options := goFitRect; LinkAnnot.Action := GotoAction; (Engine as TgtPDFEngine).AddAnnotItem(LinkAnnot); end; end; end; { ------------------------------------------------------------------------------ } { Event: on drawing hyperlinks. If this is an external hyperlink, we write it immediately. If this is a link to another location in the same document, we store it in FLinks collection (we will add it later, in SaveLinksToCheckpoints). } procedure TgtRichViewInterface.DoDrawHyperlink(Sender: TCustomRVPrint; RVData: TCustomRVData; ItemNo: Integer; R: TRect); var Target: TgtRVCheckpointName; LinkAction: TgtAnnotLinkAction; LinkAnnot: TgtPDFLinkAnnot; begin if Assigned(FOldOnDrawHyperlink) then FOldOnDrawHyperlink(Sender, RVData, ItemNo, R); Target := RVData.GetItemTag(ItemNo); if Target = '' then exit; if Target[1] = '#' then begin if rvgoSaveLinksToCheckpoints in Options then with FLinks.Add as TLinkToCheckpoint do begin CheckpointName := Copy(Target, 2, Length(Target) - 1); PageIndex := Engine.CurrentPage; Area := R; end; end else begin if rvgoSaveExternalLinks in Options then begin LinkAnnot := TgtPDFLinkAnnot.Create; LinkAnnot.Rect := gtRect(R.Left, R.Top, R.Right, R.Bottom); // LinkAnnot.BorderWidth := 1; LinkAction := TgtAnnotLinkAction.Create; LinkAction.URI := Target; LinkAnnot.Action := LinkAction; (Engine as TgtPDFEngine).AddAnnotItem(LinkAnnot); end; end; end; { ------------------------------------------------------------------------------ } procedure TgtRichViewInterface.InitLinkCollections(ARVPrint: TCustomRVPrint); begin if not(Engine is TgtPDFEngine) then exit; FOldOnDrawHyperlink := ARVPrint.OnDrawHyperlink; FOldOnDrawCheckpoint := ARVPrint.OnDrawCheckpoint; FOldProcessAfterEachPage := TgtPDFEngine(Engine) .Preferences.ProcessAfterEachPage; TgtPDFEngine(Engine).Preferences.ProcessAfterEachPage := False; ARVPrint.OnDrawHyperlink := DoDrawHyperlink; ARVPrint.OnDrawCheckpoint := DoDrawCheckpoint; FCheckpoints := TCollection.Create(TCheckpointLocation); FLinks := TCollection.Create(TLinkToCheckpoint); end; { ------------------------------------------------------------------------------ } procedure TgtRichViewInterface.DoneLinkCollections(ARVPrint: TCustomRVPrint); begin if not(Engine is TgtPDFEngine) then exit; ARVPrint.OnDrawHyperlink := FOldOnDrawHyperlink; ARVPrint.OnDrawCheckpoint := FOldOnDrawCheckpoint; TgtPDFEngine(Engine).Preferences.ProcessAfterEachPage := FOldProcessAfterEachPage; RVFreeAndNil(FCheckpoints); RVFreeAndNil(FLinks); end; {$ENDIF} { ------------------------------------------------------------------------------ } { Exporting ARVPrint using the specified Engine. if IsFormatted = False, we format ARVPrint before exporting. If ScaleToScreenDPI = True (default), we set the Engine's page size equal to the print preview size in 100% zoom, and then draw pages scaled to this size. Exporting hyperlinks is not supported in this mode. If ScaleToScreenDPI = False, it is assumed that the Engine's page size, InputXRes and InputYRes are already set according to the printer, and pages are drawn unscaled. If this is a PDF export, hyperlinks are exported according to Options property. If TRichView version is older than 17, ScaleToScreenDPI is ignored (always processed as ScaleToScreenDPI = True) In all modes, the Engine's margins and header and footer height are zeroed. If ARVPrint.OnSendingToPrinter is assigned, it is called. } procedure TgtRichViewInterface.RenderDocument(ARVPrint: TRVPrint; IsFormatted: Boolean{$IFDEF RichView17Up}; ScaleToScreenDPI: Boolean{$ENDIF}); procedure DoProgress(PageCompleted: Integer; Step: TRVPrintingStep); begin if Assigned(ARVPrint.OnSendingToPrinter) then ARVPrint.OnSendingToPrinter(ARVPrint.rv, PageCompleted, Step); end; var LI: Integer; OldUnits: TgtUnitType; begin {$IFDEF RichView16Up} ARVPrint.MetafileCompatibility := True; {$ENDIF} OldUnits := Engine.MeasurementUnit; {$IFDEF RichView17Up} if (Engine is TgtPDFEngine) and not ScaleToScreenDPI then begin InitLinkCollections(ARVPrint); FFullPageSize.cx := TCustomMainPtblRVData(ARVPrint.rv.RVData).GetPageWidth; FFullPageSize.cy := TCustomMainPtblRVData(ARVPrint.rv.RVData).GetPageHeight; FDocOffset.X := 0; FDocOffset.Y := 0; end; with IgtDocumentEngine(Engine).Page do begin LeftMargin := 0; RightMargin := 0; TopMargin := 0; BottomMargin := 0; HeaderHeight := 0; FooterHeight := 0; end; {$ENDIF} DoProgress(0, rvpsStarting); try if not IsFormatted then ARVPrint.FormatPages(rvdoALL); Engine.MeasurementUnit := muPixels; {$IFDEF RichView17Up} if ScaleToScreenDPI then begin IgtDocumentEngine(Engine).Page.Width := {$IFDEF RichView18Up} ARVPrint.GetPreview100PercentWidth(Screen.PixelsPerInch); {$ELSE} Round(ARVPrint.Preview100PercentWidth * Screen.PixelsPerInch / RV_GetPixelsPerInch); {$ENDIF} IgtDocumentEngine(Engine).Page.Height := {$IFDEF RichView18Up} ARVPrint.GetPreview100PercentHeight(Screen.PixelsPerInch); {$ELSE} Round(ARVPrint.Preview100PercentHeight * Screen.PixelsPerInch / RV_GetPixelsPerInch); {$ENDIF} end; {$ENDIF} for LI := 1 to ARVPrint.PagesCount do begin if LI = 1 then begin StartDocument; if Engine.EngineStatus <> esStarted then begin DocStarted := False; exit; end; end else IgtDocumentEngine(Engine).NewPage; {$IFDEF RichView17Up} if ScaleToScreenDPI then ARVPrint.DrawPreview(LI, Engine.Canvas, Rect(0, 0, Round(IgtDocumentEngine(Engine).Page.Width), Round(IgtDocumentEngine(Engine).Page.Height))) else ARVPrint.DrawPage(LI, Engine.Canvas, True); {$ELSE} ARVPrint.DrawPreview(LI, Engine.Canvas, Rect(0, 0, Round(IgtDocumentEngine(Engine).Page.Width), Round(IgtDocumentEngine(Engine).Page.Height))) {$ENDIF} {$IFDEF RichView17Up}DoProgress(LI, rvpsProceeding);{$ENDIF} end; {$IFDEF RichView17Up} SaveLinksToCheckpoints; {$ENDIF} EndDocument; finally {$IFDEF RichView17Up} if (Engine is TgtPDFEngine) and not ScaleToScreenDPI then DoneLinkCollections(ARVPrint); {$ENDIF} Engine.MeasurementUnit := OldUnits; DoProgress(ARVPrint.PagesCount, rvpsFinished); end; end; { ------------------------------------------------------------------------------ } { Exporting ARVHelper using the specified Engine. Before exporting, formatting ARVHelper according to the Engine's page size. Unlike TRVPrint export, we respect the Engine's margins. Hyperlinks are exported according to Options property. } procedure TgtRichViewInterface.RenderDocument(ARVHelper: TRVReportHelper); var LI, LWidth, LHeight: Integer; OldUnits: TgtUnitType; begin {$IFDEF RichView16Up} ARVHelper.MetafileCompatibility := True; {$ENDIF} OldUnits := Engine.MeasurementUnit; Engine.MeasurementUnit := muPixels; try {$IFDEF RichView17Up} if Engine is TgtPDFEngine then begin InitLinkCollections(ARVHelper); with IgtDocumentEngine(Engine).Page do begin FFullPageSize.cx := Round(Width); FFullPageSize.cy := Round(Height); FDocOffset.X := Round(LeftMargin); FDocOffset.Y := Round(TopMargin + HeaderHeight); end; end; {$ENDIF} try with IgtDocumentEngine(Engine).Page do begin LWidth := Round(Width - LeftMargin - RightMargin); LHeight := Round(Height - TopMargin - BottomMargin - HeaderHeight - FooterHeight); end; StartDocument; if Engine.EngineStatus <> esStarted then begin DocStarted := False; exit; end; ARVHelper.Init(Engine.Canvas, Round(LWidth)); LI := 0; while ARVHelper.FormatNextPage(Round(LHeight)) do begin if LI <> 0 then IgtDocumentEngine(Engine).NewPage; ARVHelper.DrawPage(LI + 1, Engine.Canvas, True, LHeight); Inc(LI); end; {$IFDEF RichView17Up} SaveLinksToCheckpoints; {$ENDIF} EndDocument; finally {$IFDEF RichView17Up} if Engine is TgtPDFEngine then DoneLinkCollections(ARVHelper); {$ENDIF} end; finally Engine.MeasurementUnit := OldUnits; end; end; {$ELSE} procedure TgtRichViewInterface.RenderDocument(ARVPrint: TRVPrint; IsFormatted: Boolean{$IFDEF RichView17Up}; ScaleToScreenDPI: Boolean{$ENDIF}); begin end; procedure TgtRichViewInterface.RenderDocument(ARVHelper: TRVReportHelper); begin end; {$IFEND} end.