Code : Tout sélectionner
;
; Print text
; F.Weil : 20040726
;
; Here is a sample code to touch what is text printing using full bitmap drawing.
; It is Windows API dependant. I guess a Linux coder would easily add the required lines, maybe coding conditional compiler directives.
; This code does not apply to Rich Edit text. Only to text printing with no embedding.
; Easy to customize however.
; ====================================================
; Voici un programme permettant de mettre les doigts dans l'impression de texte passant par des bitmaps.
; Ce code est dépendant de Windows. Je pense qu'un codeur Linux devrait pouvoir ajouter le pendant des commandes appropriées, éventuellement en plaçant des directives de compilation conditionnelle
; Ce code ne s'applique pas à du texte de type Rich Edit. Seulement au texte non décoré.
; Toutefois l'amélioration en est relativement accessible.
;
Enumeration
#Window_Preview
#Image_Preview
#Image_FullPrint
#Gadget_Image_Preview
#DrawingFont
#Requester_OK = 6
#Requester_NO
EndEnumeration
#MAX_STRING_LENGTH = $400000
Structure StringBytes
Bytes.b[#MAX_STRING_LENGTH]
EndStructure
Global NewList Print_text_PageName.s()
;
; Set strings length at a # max value than PureBasic's default
; ========================================
; Modifie la longueur max des chaines de caractères.
;
Procedure ManipulationBufferSize(Bytes)
PBStringBase.l = 0
PBMemoryBase.l = 0
!MOV eax, dword [PB_StringBase]
!MOV [esp+4], eax
!MOV eax, dword [PB_MemoryBase]
!MOV [esp+8], eax
HeapReAlloc_(PBMemoryBase, #GMEM_ZEROINIT, PBStringBase, Bytes)
!MOV dword [PB_StringBase], eax
;Debug "ManipulationBufferSize : max length of string set to : " + Str(Bytes)
ProcedureReturn Bytes
EndProcedure
;
; Split a full text placed in StringIn, in lines corresponding to a given drawing width. The text is returned to the caller
; =========================================================================
; Découpe un texte entier placé dans StringIn pour faire correspondre les lignes à une largeur de dessin donné.
; Le texte transformé est retourné à l'appelant.
;
Procedure.s FoxLinedText2D(StringIn.s, PixelWidth.l)
LenStringIn = Len(StringIn)
LenStringOut = LenStringIn + 3 * (Int(LenStringIn / PixelWidth) + 1)
StringOut.s = Space(LenStringOut)
*MyStringIn.StringBytes = @StringIn
*MyStringOut.StringBytes = @StringOut
j = 0
For i = 0 To LenStringIn - 1
Debug "k="+Str(k) + " pixelwidth="+Str(pixelwidth)
Cod.b = *MyStringIn\Bytes[i]
If Cod = 13 Or Cod = ' ' Or Cod = '.' Or Cod = ','
LastWordBreakInPosition = i
LastWordBreakOutPosition = j
If Cod = 13
LastLineBreak = j + 3
EndIf
EndIf
If k > PixelWidth And i > 0 ; means the counter reached the right margin
io = i
jo = j
i = LastWordBreakInPosition + 1
j = LastWordBreakOutPosition
k = 0
*MyStringOut\Bytes[j] = 13
*MyStringOut\Bytes[j + 1] = 10
*MyStringOut\Bytes[j + 2] = *MyStringIn\Bytes[i] ; Asc(Mid(StringIn, i, 1))
LastLineBreak = j + 2
If i = LastBreakDone
LastWordBreakInPosition = io - 1
LastWordBreakOutPosition = jo
EndIf
LastBreakDone = i
j + 2
Else
*MyStringOut\Bytes[j] = *MyStringIn\Bytes[i] ; Asc(Mid(StringIn, i, 1))
EndIf
k = Len(Mid(StringOut, LastLineBreak, j - LastLineBreak))
j + 1
Next
*MyStringOut\Bytes[j] = 0
ProcedureReturn StringOut
EndProcedure
;
; Build a preview image from the image stored in FileName, using desktop metrics
; ====================================================
; Construit une image preview à partir de l'original situé dans le fichier cité, en utilisant la métrique de l'écran
;
Procedure MakePreview(FileName.s)
ImageID_FullSize = LoadImage(#Image_FullPrint, FileName)
PreviewWidth = ImageWidth(ImageID_FullSize)
PreviewHeight = ImageHeight(ImageID_FullSize)
HRatio.f = 1.2 * PreviewWidth / GetSystemMetrics_(#SM_CXSCREEN)
VRatio.f = 1.2 * PreviewHeight / GetSystemMetrics_(#SM_CYSCREEN)
If HRatio => VRatio
ImageWidth = PreviewWidth / HRatio
ImageHeight = PreviewHeight / HRatio
ImageID_Preview = ResizeImage(#Image_FullPrint, ImageWidth, ImageHeight)
Else
ImageWidth = PreviewWidth / VRatio
ImageHeight = PreviewHeight / VRatio
ImageID_Preview = ResizeImage(#Image_FullPrint, ImageWidth, ImageHeight)
EndIf
;ImageID(#Image_FullPrint)
StartDrawing(ImageOutput(#Image_FullPrint))
DrawingMode(4)
Box(0, 0, ImageWidth, ImageHeight, #Black)
StopDrawing()
ProcedureReturn ImageID_Preview
EndProcedure
;
; Draw the text in images build to the printer choosen inside this procedure.
; If the given printer allows both Portrait / Landscape, just select the desired parameters in the printer requester.
; This procedure does support multiple pages. Required pages are drawn in bitmaps queued in files for print / preview.
; The queued files names are stored in Print_text_PageName() linked list.
;
; CPI (characters per inch) and font name are received from the caller to make this procedure more flexible.
; All required metrics are turned to available printer parameters. When selecting a printer the metrics are updated for this printer.
;
; The preview feature is actually not fast. I will go back on this further more in some days / weeks.
; =========================================================================
; Dessine le texte dans les images nécessaires à l'impression éventuellement multi-pages.
; L'imprimante est choisie à l'intérieur de la présente procédure. Si l'imprimante choisie autorise par exemple le portrait / paysage
; les paramètres sont automatiquement recalculés en fonction du choix opéré.
; L'impression est générée dans autant de bitmaps que de pages sont nécessaires. Les bitmaps sont stockés en attente sur le disque.
; Les noms des bitmaps sont stockés dans la liste Print_text_PageName().
;
; Les paramètres CPI (nombre de caractères au pouce) et FontName (nom de la police), sont donnés pour rendre la procédure plus flexible.
; Toute la métrique nécessaire et suffisante est calculée pour correspondre à l'imprimante choisie au moment de l'impression.
;
; La fonction de prévisualisation est actuellement peu performante. Je reprendrai ce point dans quelques jours / semaines.
;
Procedure PrintText(Text.s, CPI.l, FontName.s)
ClearList(Print_text_PageName())
If PrintRequester()
printer_DC.l = StartDrawing(PrinterOutput())
If printer_DC
HorizontalDPI = GetDeviceCaps_(printer_DC,#LOGPIXELSX)
VerticalDPI = GetDeviceCaps_(printer_DC,#LOGPIXELSY)
FontSize = HorizontalDPI / CPI
FontHeight = FontSize * 1.6
PrinterLeftMargin = GetDeviceCaps_(printer_DC,#PHYSICALOFFSETY)
PrinterTopMargin = GetDeviceCaps_(printer_DC,#PHYSICALOFFSETX)
UserMargin = HorizontalDPI
PixelWidth = GetDeviceCaps_(printer_DC,#PHYSICALWIDTH)
PixelHeight = GetDeviceCaps_(printer_DC,#PHYSICALHEIGHT)
PrinterRowHeight = FontHeight
StopDrawing()
ImageID_FullPrint = CreateImage(#Image_FullPrint, PixelWidth, PixelHeight)
If ImageID_FullPrint
FontID=LoadFont(#DrawingFont, FontName, FontSize, #PB_Font_HighQuality)
StartDrawing(ImageOutput(#Image_FullPrint))
Box(0, 0, PixelWidth, PixelHeight, #White)
TextOut.s = FoxLinedText2D(Text, PixelWidth / fontsize)
BackColor(RGB(255, 255, 255))
FrontColor(RGB(0, 0, 0))
DrawingMode(1)
LineNumber = 0
While TextOut <> ""
LineOut.s = Mid(TextOut, 1, FindString(TextOut, Chr(13) + Chr(10), 1) - 1)
TextOut = Mid(TextOut, FindString(TextOut, Chr(13) + Chr(10), 1) + 2, Len(TextOut) - FindString(TextOut, Chr(13) + Chr(10), 1) - 2 + 1)
;Locate(, )
DrawText(userMargin,UserMargin + PrinterRowHeight * LineNumber,LineOut)
LineNumber + 1
If UserMargin + PrinterRowHeight * LineNumber => PixelHeight - UserMargin
AddElement(Print_text_PageName())
Print_text_PageName() = "Print text." + Str(ElapsedMilliseconds()) + ".jpg"
Debug "Adding page : " + Print_text_PageName()
SaveImage(#Image_FullPrint, Print_text_PageName(), #PB_ImagePlugin_JPEG)
StopDrawing()
FreeImage(#Image_FullPrint)
ImageID_FullPrint = CreateImage(#Image_FullPrint, PixelWidth, PixelHeight)
FontID=LoadFont(#DrawingFont, FontName, FontSize, #PB_Font_HighQuality)
StartDrawing(ImageOutput(#Image_FullPrint))
Box(0, 0, PixelWidth, PixelHeight, #White)
DrawingFont(FontID)
BackColor(RGB(255, 255, 255))
FrontColor(RGB(0, 0, 0))
DrawingMode(1)
LineNumber = 0
EndIf
Wend
StopDrawing()
AddElement(Print_text_PageName())
Print_text_PageName() = "Print text." + Str(ElapsedMilliseconds()) + ".jpg"
Debug "Adding page : " + Print_text_PageName()
SaveImage(#Image_FullPrint, Print_text_PageName(), #PB_ImagePlugin_JPEG)
FreeImage(#Image_FullPrint)
EndIf
Select MessageRequester("Print request", "Do you want to print (OK) / Preview (No) / Give up (Cancel)", #PB_MessageRequester_YesNoCancel)
Case #Requester_OK
If StartPrinting("PureBasic Test")
If StartDrawing(PrinterOutput())
ResetList(Print_text_PageName())
While NextElement(Print_text_PageName())
Debug "Printing page : " + Print_text_PageName()
LoadImage(#Image_FullPrint, Print_text_PageName())
DrawImage(ImageID(#Image_FullPrint), 0, 0)
DeleteFile(Print_text_PageName())
DeleteElement(Print_text_PageName())
NewPrinterPage()
Wend
StopPrinting()
StopDrawing()
EndIf
EndIf
Case #Requester_NO
ResetList(Print_text_PageName())
NextElement(Print_text_PageName())
PreviewWidth = ImageWidth(#Image_FullPrint)
PreviewHeight = ImageHeight(#Image_FullPrint)
HRatio.f = 1.2 * PreviewWidth / GetSystemMetrics_(#SM_CXSCREEN)
VRatio.f = 1.2 * PreviewHeight / GetSystemMetrics_(#SM_CYSCREEN)
If HRatio => VRatio
ImageWidth = PreviewWidth / HRatio
ImageHeight = PreviewHeight / HRatio
Else
ImageWidth = PreviewWidth / VRatio
ImageHeight = PreviewHeight / VRatio
EndIf
If OpenWindow(#Window_Preview, 0, 0, ImageWidth, ImageHeight, "Preview window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
AddKeyboardShortcut(#Window_Preview, #PB_Shortcut_Escape, #PB_Shortcut_Escape)
AddKeyboardShortcut(#Window_Preview, #PB_Shortcut_Up, #PB_Shortcut_Up)
AddKeyboardShortcut(#Window_Preview, #PB_Shortcut_Down, #PB_Shortcut_Down)
;If CreateGadgetList(WindowID(#Window_Preview))
ImageGadget(#Gadget_Image_Preview, 0, 0, ImageWidth, ImageHeight, MakePreview(Print_text_PageName()))
;EndIf
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Quit = #True
Case #PB_Event_Menu
Select EventMenu()
Case #PB_Shortcut_Escape
Quit = #True
Case #PB_Shortcut_Up
PreviousElement(Print_text_PageName())
SetGadgetState(#Gadget_Image_Preview, MakePreview(Print_text_PageName()))
Case #PB_Shortcut_Down
NextElement(Print_text_PageName())
SetGadgetState(#Gadget_Image_Preview, MakePreview(Print_text_PageName()))
EndSelect
EndSelect
Until Quit
EndIf
EndSelect
EndIf
EndIf
ForEach Print_text_PageName()
LastElement(Print_text_PageName())
DeleteFile(Print_text_PageName())
DeleteElement(Print_text_PageName())
Next
EndProcedure
;
; The Main program cnotains initalization for using JPEG files and enhancing the string max length.
; Then you can just place any text in the parameter to call PrintText() with the desired font size and name.
; ===================================================================
; Le programme principal contient simplement les initialisations permettant d'utiliser les images JPEG et les chaines de longueur non standard.
; Il suffit d'appeler PrintText() avec nu texte quelconque et les paramètres de police souhaités.
;
Text.s
;ManipulationBufferSize(#MAX_STRING_LENGTH)
UseJPEGImageDecoder()
UseJPEGImageEncoder()
If ReadFile(0, "C:\Documents and Settings\Yves\Mes documents\Developpement\Théorie\loupe.pb")
DataLength = Lof(0)
*Buffer = AllocateMemory(DataLength)
ReadData(0,*Buffer, DataLength)
CloseFile(0)
Text = PeekS(*Buffer)
PrintText(Text, 12, "Verdana")
Else
Debug "Erreur d'ouverture du fichier"
EndIf
End