Xojo Developer Conference
25/27th April 2018 in Denver.
MBS Xojo Conference
6/7th September 2018 in Munich, Germany.

Platforms to show: All Mac Windows Linux Cross-Platform

/DynaPDF/Text Positions
Function:
You find this example project in your Plugins Download as a Xojo project file within the examples folder: /DynaPDF/Text Positions
This example is the version from Sat, 19th Jan 2018.
Project "Text Positions.rbp"
Class App Inherits Application
Const kEditClear = "&Delete"
Const kFileQuit = "&Quit"
Const kFileQuitShortcut = ""
End Class
Class MainWindow Inherits Window
EventHandler Sub Open() dim f as FolderItem = FindFile("license.pdf") dim p as new MyDynapdfMBS p.SetLicenseKey "Pro" // For this example you can use a Pro or Enterprise License call p.CreateNewPDF // Skip anything that is not required call p.SetImportFlags p.kifImportAll+p.kifImportAsPage // From which PDF file do you want to extract the images? call p.OpenImportFile(f, p.kptOpen, "") // Comment this out if you want to extract the images from specific pages only call p.ImportPDFFile(1, 1.0, 1.0) call p.CloseImportFile dim parser as new MyDynaPDFParseInterfaceMBS(p) 'If you want to create a multipage TIFF then create the output image here 'and call AddImage() only in the callback function. After the loop 'returns call CloseImage() to close the image file. call p.EditPage 1 call p.ParseContent(parser, p.kpfNone) call p.EndPage self.texts = parser.Texts self.pdf = p End EventHandler
EventHandler Sub Paint(g As Graphics, areas() As REALbasic.Rect) const factor = 2.0 dim Page as DynaPDFPageMBS = pdf.GetPage(1) dim bbox as DynaPDFRectMBS = page.BBox(page.kpbMediaBox) dim PageWidth as integer = bbox.Width dim PageHeight as integer = abs(bbox.Bottom - bbox.top) // we draw pdf as background dim pic as Picture = pdf.RenderPagePicture(1, PageWidth*factor, PageHeight*factor, 2, nil) g.DrawPicture pic, 0, 0 // now draw text blocks for each t as PDFText in texts dim m as DynaPDFMatrixMBS = t.EffectiveMatrix dim x1 as Double = 0 dim y1 as Double = 0 dim x2 as Double = t.Width dim y2 as Double = t.State.FontSize dim xx1 as Double = x1 * M.a + y1 * M.c + M.x dim yy1 as Double = x1 * M.b + y1 * M.d + M.y dim xx2 as Double = x2 * M.a + y2 * M.c + M.x dim yy2 as Double = x2 * M.b + y2 * M.d + M.y // swap coordinates from bottom-up in PDF to top-down in Xojo yy1 = PageHeight - yy1 yy2 = PageHeight - yy2 g.ForeColor = &cCCCCFF dim xxm as Double = min(xx1, xx2) dim yym as Double = min(yy1, yy2) g.DrawRect xxm*factor, yym*factor, abs(xx2-xx1)*factor, abs(yy2-yy1)*factor g.ForeColor = &cFF0000 dim fx as Double = 0 dim fy as Double = t.State.FontSize 'dim MM as DynaPDFMatrixMBS = t.Matrix * t.State.matrix 'dim ffx as Double = fx * M.b + fy * M.d '+ M.y dim ffy as Double = fx * M.b + fy * M.d '+ M.y g.TextSize = ffy * factor if t.KerningW <> nil then for each k as DynaPDFTextRecordWMBS in t.KerningW x1 = x1 - k.Advance x2 = x2 - k.Advance xx1 = x1 * M.a + y1 * M.c + M.x yy1 = x1 * M.b + y1 * M.d + M.y xx2 = x2 * M.a + y2 * M.c + M.x yy2 = x2 * M.b + y2 * M.d + M.y // swap coordinates from bottom-up in PDF to top-down in Xojo yy1 = PageHeight - yy1 yy2 = PageHeight - yy2 // drawing here will not match what DynaPDF draws as we do not take style and spacing in account g.DrawString k.Text, xx1*factor, (yy1)*factor x1 = x1 + k.Width x2 = x2 + k.Width next elseif t.KerningA <> nil then for each k as DynaPDFTextRecordAMBS in t.KerningA x1 = x1 - k.Advance x2 = x2 - k.Advance xx1 = x1 * M.a + y1 * M.c + M.x yy1 = x1 * M.b + y1 * M.d + M.y xx2 = x2 * M.a + y2 * M.c + M.x yy2 = x2 * M.b + y2 * M.d + M.y // swap coordinates from bottom-up in PDF to top-down in Xojo yy1 = PageHeight - yy1 yy2 = PageHeight - yy2 // translate native encoding to Unicode dim width as Double = 0 dim decoded as Boolean dim text as string = DynaPDFMBS.TranslateRawCode(t.state.FontHandle, k.Text, width, decoded, t.state.CharSpacing, t.state.WordSpacing, t.State.TextScale) // drawing here will not match what DynaPDF draws as we do not take style and spacing in account g.DrawString Text, xx1*factor, (yy1)*factor x1 = x1 + Width x2 = x2 + Width next end if next End EventHandler
Property pdf As MyDynaPDFMBS
Property texts() As PDFText
End Class
MenuBar MainMenuBar
MenuItem FileMenu = "&File"
MenuItem FileQuit = "#App.kFileQuit"
MenuItem EditMenu = "&Edit"
MenuItem EditUndo = "&Undo"
MenuItem EditSeparator1 = "-"
MenuItem EditCut = "Cu&t"
MenuItem EditCopy = "&Copy"
MenuItem EditPaste = "&Paste"
MenuItem EditClear = "#App.kEditClear"
MenuItem EditSeparator2 = "-"
MenuItem EditSelectAll = "Select &All"
End MenuBar
Class PDFState
Sub Constructor(other as PDFState) self.CharSpacing = other.CharSpacing self.ExtGState = other.ExtGState self.FontHandle = other.FontHandle self.FontInfo = other.FontInfo self.FontName = other.FontName self.FontSize = other.FontSize self.FontStyle = other.FontStyle self.MiterLimit = other.MiterLimit self.textDrawMode = other.textDrawMode self.TextScale = other.TextScale self.WordSpacing = other.WordSpacing self.matrix = new DynaPDFMatrixMBS(other.matrix) // copy End Sub
Sub constructor() matrix = new DynaPDFMatrixMBS // makes new identity matrix FontSize = 1.0 CharSpacing = 0.0 TextDrawMode = DynaPDFMBS.kdmNormal TextScale = 100.0 WordSpacing = 0.0 End Sub
Property CharSpacing As Double
Property ExtGState As DynaPDFExtGState2MBS
Property FontHandle As Integer
Property FontInfo As DynaPDFFontInfoMBS
Property FontName As String
Property FontSize As double
Property FontStyle As Integer
Property Leading As Double
Property MiterLimit As double
Property TextScale As Double
Property WordSpacing As Double
Property matrix As DynaPDFMatrixMBS
Property textDrawMode As Integer
End Class
Class MyDynaPDFMBS Inherits DynaPDFMBS
EventHandler Function Error(ErrorCode as integer, ErrorMessage as string, ErrorType as integer) As integer // output all messages on the console: System.DebugLog str(ErrorCode)+": "+ErrorMessage // and display dialog: Dim d as New MessageDialog //declare the MessageDialog object Dim b as MessageDialogButton //for handling the result d.icon=MessageDialog.GraphicCaution //display warning icon d.ActionButton.Caption="Continue" d.CancelButton.Visible=True //show the Cancel button // a warning or an error? if BitAnd(ErrorType, me.kE_WARNING) = me.kE_WARNING then // if user decided to ignore, we'll ignore if IgnoreWarnings then Return 0 d.Message="A warning occurred while processing your PDF code." // we add a third button to display all warnings d.AlternateActionButton.Caption = "Ignore warnings" d.AlternateActionButton.Visible = true else d.Message="An error occurred while processing your PDF code." end if d.Explanation = str(ErrorCode)+": "+ErrorMessage b=d.ShowModal //display the dialog Select Case b //determine which button was pressed. Case d.ActionButton Return 0 // ignore Case d.AlternateActionButton IgnoreWarnings = true Return 0 // ignore Case d.CancelButton Return -1 // stop End select End EventHandler
Property IgnoreWarnings As Boolean
End Class
Class MyDynaPDFParseInterfaceMBS Inherits DynaPDFParseInterfaceMBS
EventHandler Function BeginTemplate(ObjectPtr as integer, Handle as integer, BBox as DynaPDFRectMBS, Matrix as DynaPDFMatrixMBS) As integer current.matrix = current.matrix * matrix End EventHandler
EventHandler Sub MulMatrix(ObjectPtr as integer, matrix as DynaPDFMatrixMBS) current.matrix = current.matrix * matrix End EventHandler
EventHandler Function RestoreGraphicState() As integer current = states.pop End EventHandler
EventHandler Function SaveGraphicState() As integer states.Append current current = new PDFState(Current) End EventHandler
EventHandler Sub SetCharSpacing(ObjectPtr as integer, Value as double) current.CharSpacing = value End EventHandler
EventHandler Sub SetExtGState(ObjectPtr as integer, GS as DynaPDFExtGState2MBS) current.ExtGState = gs End EventHandler
EventHandler Sub SetFont(ObjectPtr as integer, fontType as integer, Embedded as boolean, FontName as string, Style as integer, FontSize as double, FontHandle as integer, FontInfo as DynaPDFFontInfoMBS) current.FontName = FontName current.FontStyle = Style current.FontSize = FontSize current.FontInfo = FontInfo current.FontHandle = FontHandle End EventHandler
EventHandler Sub SetLeading(ObjectPtr as integer, Value as double) current.Leading = value End EventHandler
EventHandler Sub SetMiterLimit(ObjectPtr as integer, Value as double) current.MiterLimit = value End EventHandler
EventHandler Sub SetTextDrawMode(ObjectPtr as integer, Mode as integer) current.textDrawMode = mode End EventHandler
EventHandler Sub SetTextScale(ObjectPtr as integer, Value as double) current.TextScale = value End EventHandler
EventHandler Sub SetWordSpacing(ObjectPtr as integer, Value as double) current.WordSpacing = value End EventHandler
EventHandler Function ShowTextArrayA(ObjectPtr as integer, Matrix as DynaPDFMatrixMBS, Kerning() as DynaPDFTextRecordAMBS, Count as integer, Width as double) As integer dim t as new PDFText t.State = new PDFState(current) t.Count = Count t.Width = Width t.KerningA = Kerning t.KerningW = nil t.Matrix = matrix texts.Append t End EventHandler
EventHandler Function ShowTextArrayW(Source() as DynaPDFTextRecordAMBS, Matrix as DynaPDFMatrixMBS, Kerning() as DynaPDFTextRecordWMBS, Count as integer, Width as double, Decoded as boolean) As integer dim t as new PDFText t.Source = Source t.State = new PDFState(current) t.Count = Count t.Width = Width t.KerningW = Kerning t.KerningA = nil t.Matrix = matrix texts.Append t End EventHandler
Sub Constructor(p as MyDynaPDFMBS) self.current = new PDFState self.pdf = p End Sub
Property States() As PDFState
Property Texts() As PDFText
Property current As PDFState
Property pdf As dynaPDFmbs
End Class
Module UtilModule
Function FindFile(name as string) As FolderItem // Look for file in parent folders from executable on dim parent as FolderItem = app.ExecutableFile.Parent while parent<>Nil dim file as FolderItem = parent.Child(name) if file<>Nil and file.Exists then Return file end if parent = parent.Parent wend End Function
Sub Transform(m as DynaPDFMatrixMBS, byref x as Double, byref y as double) dim tx as double = x x = tx * M.a + y * M.c + M.x y = tx * M.b + y * M.d + M.y End Sub
End Module
Class PDFText
Function EffectiveMatrix() As DynaPDFMatrixMBS return matrix * state.matrix End Function
Property Count As Integer
Property Decoded As boolean
Property KerningA() As DynapdfTextRecordAMBS
Property KerningW() As DynapdfTextRecordWMBS
Property Matrix As DynapdfMatrixMBS
Property Source() As DynapdfTextRecordAMBS
Property State As PDFState
Property Width As Double
End Class
End Project

See also:

Feedback, Comments & Corrections

The items on this page are in the following plugins: MBS DynaPDF Plugin.




Links
MBS Xojo Chart Plugins