I found that the multiple outputs within the loop including the "set /P" and file size readings were the cause of the slowdown (non-linear).
I calculated the positions (making pads of the strings) and moved to a single output and removed the query of the file size and the performance
doubled.
However, there are now many calls to the pad function. Macros could be created. In addition, the function that calculates the length of the string could also be improved.
Here I have a very fast version which is not very long. I recently tested it, it should work.
inline version, size returns in the "#" variable:
Code: Select all
set "$=A!Str!" & set "#="
for %%P in (4096 2048 1024 512 256 128 64 32 16) do if "!$:~%%P!" NEQ "" set /a "#+=%%P" & set "$=!$:~%%P!"
set "$=!$:~1!FEDCBA9876543210" & set /a #+=0x!$:~15,1!
macro version on a single line, does not use setlocal to return the value but uses a fixed one:
Code: Select all
rem macro $strlen, return $len
set "$strlen=for %%# in (1 2) do if %%#==2 ( for /f %%1 in ("^^!args^^!") do (set "$=A^^!%%1^^!" & set "$len=" & ( for %%] in (4096 2048 1024 512 256 128 64 32 16) do if "^^!$:~%%]^^!" NEQ "" set /a "$len+=%%]" & set "$=^^!$:~%%]^^!" ) & set "$=^^!$:~1^^!FEDCBA9876543210" & set /a $len+=0x^!$:~15,1^! ) ) else set args="
set "str=foo bar"
%$strlen% Str
echo length=!$len!
the new code
Code: Select all
@echo off&setlocal EnableExtensions DisableDelayedExpansion
if "%~1"=="/?" call :help "Convert Text to PDF" &exit /b 0
set "Letter=pageHeight=792, pageWidth=612"
set "A4=pageHeight=842, pageWidth=595"
set "A3=pageHeight=1190, pageWidth=842"
set "inFile=%~1"
if not exist "%inFile%" call :help "Error: inFile does not exist.">&2 &exit /b 1
if exist "%inFile%\" call :help "Error: inFile does not exist.">&2 &exit /b 1
for %%i in ("%inFile%") do if %%~zi equ 0 call :help "Error: inFile is empty.">&2 &exit /b 1
set "outFile=%~2"
if not defined outFile call :help "Error: outFile not specified.">&2 &exit /b 1
for %%i in ("%outFile%") do if /i "%%~xi" neq ".pdf" set "outfile=%outfile%.pdf"
set /a "%A4%, tabWidth=8, fontSize=10, landscape=0, objects=5, pages=0"
:opt_loop
if "%~3"=="" goto end_opt
set "opt=%~3"
if /i "%opt%"=="/A4" (
set /a "%A4%"
) else if /i "%opt%"=="/A3" (
set /a "%A3%"
) else if /i "%opt%"=="/Letter" (
set /a "%Letter%"
) else if /i "%opt:~0,3%"=="/T:" (
set /a "tabWidth=%opt:~3%"
) else if /i "%opt:~0,3%"=="/F:" (
set /a "fontSize=%opt:~3%"
) else if /i "%opt%"=="/L" (
set /a "landscape=1"
) else call :help "Error: Invalid option.">&2 &exit /b 1
shift /3
goto opt_loop
:end_opt
2>&1 (>"%outFile%" type nul)|>nul find /v ""&&(call :help "Error: Unabe to write to outFile.">&2 &exit /b 1)
set "tab= "
set "spcs= "
if not exist "%__APPDIR__%wbem\WMIC.exe" for /f "tokens=1,2*" %%a in ('reg query "HKCU\Control Panel\International"^|findstr /i "\<[is]Date\>"') do set "%%a=%%c"
if not exist "%__APPDIR__%wbem\WMIC.exe" (
for /f "tokens=1-6 delims=:.,%sDate%" %%a in ("%date:* =%,%time: =0%") do (
setlocal EnableExtensions EnableDelayedExpansion
if !iDate!==0 (set mm=0%%a&set dd=0%%b&set yy=%%c) else if !iDate!==1 (set dd=0%%a&set mm=0%%b&set yy=%%c) else (set yy=%%a&set mm=0%%b&set dd=0%%c)
(set h=%%d&set m=%%e&set s=%%f)
)
if 1!yy! LSS 200 if 1!yy! LSS 170 (set yy=20!yy!) else (set yy=19!yy!)
set "LocalDateTime=!yy!!mm:~-2!!dd:~-2!!h!!m!!s!"
) else for /f "delims=." %%a in ('WMIC OS Get LocalDateTime /value') do for /f %%b in ("%%a") do (
set "%%b"
setlocal EnableExtensions EnableDelayedExpansion
)
if !tabWidth! lss 2 set "tabWidth=2"
if !fontSize! lss 1 set "fontSize=1"
if !landscape! neq 0 set /a "_tmp=pageWidth, pageWidth=pageHeight, pageHeight=_tmp"
for /f %%i in ('type "!inFile!"^|find /c /v ""') do set /a "lineHight=(fontSize*12)/10, linesInPage=(pageHeight-72)/lineHight, pageCnt=%%i/linesInPage, linesInLast=%%i %% linesInPage, hMinus40=pageHeight-40"
if !linesInPage! lss 1 set "linesInPage=1"
if !linesInLast! equ 0 (set /a "linesInLast=linesInPage") else set /a "pageCnt+=1"
>"!outFile!" echo(%%PDF-1.1
for %%i in ("!outFile!") do set "objPos[1]=%%~zi"
>>"!outFile!" (
echo(1 0 obj
echo(^<^<
echo(/CreationDate ^(D:!LocalDateTime!^)
echo(/Producer ^(text2pdf.bat^)
echo(/Title ^(text2pdf^)
echo(^>^>
echo(endobj
)
for %%i in ("!outFile!") do set "objPos[2]=%%~zi"
>>"!outFile!" (
echo(2 0 obj
echo(^<^<
echo(/Type /Catalog
echo(/Pages 3 0 R
echo(^>^>
echo(endobj
)
for %%i in ("!outFile!") do set "objPos[4]=%%~zi"
>>"!outFile!" (
echo(4 0 obj
echo(^<^<
echo(/Type /Font
echo(/Subtype /Type1
echo(/Name /F1
echo(/BaseFont /Courier
echo(/Encoding /WinAnsiEncoding
echo(^>^>
echo(endobj
)
for %%i in ("!outFile!") do set "objPos[5]=%%~zi"
>>"!outFile!" (
echo(5 0 obj
echo(^<^<
echo(/Font ^<^< /F1 4 0 R ^>^>
echo(/ProcSet [ /PDF /Text ]
echo(^>^>
echo(endobj
)
for %%i in ("!outFile!") do set "fsize=%%~zi"
rem 43sec, 18sec, 16sec
rem for %%i in ("!outFile!") do echo 1 fsize:!fsize! real:%%~zi >Con:
<!inFile! >>"!outFile!" (
for /l %%h in (1 1 !pageCnt!) do (
set /a "objects+=1, nextObject=objects+1, pages+=1"
set "pageObj[!pages!]=!objects!"
set /a "objPos[!objects!]=fsize"
call :pad4 objects objectsP
call :pad4 nextObject nextObjectP
echo(!objectsP! 0 obj
echo(^<^<
echo(/Type /Page
echo(/Parent 3 0 R
echo(/Resources 5 0 R
echo(/Contents !nextObjectP! 0 R
echo(^>^>
echo(endobj
set /a "fsize+=94"
set /a "objects+=1, nextObject+=1"
set /a "objPos[!objects!]=fsize"
call :pad4 objects objectsP
call :pad4 nextObject nextObjectP
echo(!objectsP! 0 obj
echo(^<^<
echo(/Length !nextObjectP! 0 R
echo(^>^>
echo(stream
set /a "fsize+=46"
set /a "streamPos=fsize"
call :pad4 fontSize fontSizeP
call :pad4 hMinus40 hMinus40P
call :pad4 lineHight lineHightP
echo(BT
echo(/F1 !fontSizeP! Tf
echo(1 0 0 1 50 !hMinus40P! Tm
echo(!lineHightP! TL
set /a "fsize+=46"
if %%h equ !pageCnt! (set "n=!linesInLast!") else set "n=!linesInPage!"
for /l %%j in (1 1 !n!) do (
set "ln="&set /p "ln="
if defined ln (
rem call :proc_line
for /f "tokens=1* delims=%tab%" %%I in ("X!ln!") do setlocal EnableExtensions DisableDelayedExpansion &if "%%J" neq "" (
endlocal
set "str=X!ln!"
set "len=0"
for /l %%M in (12 -1 0) do (
set /a "len|=1<<%%M"
for %%L in (!len!) do if "!str:~%%L,1!"=="" set /a "len&=~1<<%%M"
)
set /a "len-=1"
call :tab_iter
) else endlocal
for %%I in ("\=\\" "(=\(" ")=\)") do set "ln=!ln:%%~I!"
)
set "str=X!ln!"
set "len=0"
for /l %%M in (12 -1 0) do (
set /a "len|=1<<%%M"
for %%L in (!len!) do if "!str:~%%L,1!"=="" set /a "len&=~1<<%%M"
)
set /a "len-=1"
echo(^(!ln!^)'
set /a "fsize+=len+1+3+2"
)
echo(^(^)'
echo(ET
set /a "fsize+=3+2+2+2"
set /a "streamLen=fsize-streamPos"
echo(endstream
echo(endobj
set /a "fsize+=19"
set /a "objects+=1, nextObject+=1"
set /a "objPos[!objects!]=fsize"
call :pad4 objects objectsP
call :pad6 streamLen streamLenP
echo(!objectsP! 0 obj
echo(!streamLenP!
echo(endobj
set /a "fsize+=28"
)
)
for %%i in ("!outFile!") do set "objPos[3]=%%~zi"
>>"!outFile!" (
echo(3 0 obj
echo(^<^<
echo(/Type /Pages
echo(/Count !pages!
echo(/MediaBox [ 0 0 !pageWidth! !pageHeight! ]
<nul set /p "=/Kids [ "
for /l %%i in (1 1 !pages!) do <nul set /p "=!pageObj[%%i]! 0 R "
echo(]
echo(^>^>
echo(endobj
)
for %%i in ("!outFile!") do set "xrefPos=%%~zi"
>>"!outFile!" (
echo(xref
echo(0 !nextObject!
echo(0000000000 65535 f
for /l %%i in (1 1 !objects!) do (
set "pos=0000000000!objPos[%%i]!"
echo(!pos:~-10! 00000 n
)
echo(trailer
echo(^<^<
echo(/Size !nextObject!
echo(/Root 2 0 R
echo(/Info 1 0 R
echo(^>^>
echo(startxref
echo(!xrefPos!
echo(%%%%EOF
)
exit /b 0
:tab_iter
set i=0
rem set /a cti+=1
rem echo call !cti!>con:
:loop
For /L %%. in (1,1,250) do (
if !i! lss !len! (
set /a "nxt=!i!+1"
for %%I in (!i!) do (
if "!ln:~%%I,1!"=="%tab%" (
set /a "d=0-(%%I %% tabWidth)+tabWidth, e=nxt, nxt+=d-1, len+=d-1"
for /f "tokens=1,2" %%d in ("!d! !e!") do set "ln=!ln:~0,%%I!!spcs:~0,%%d!!ln:~%%e!"
)
)
set /a i=nxt
) else exit/b
)
goto :loop
exit /b
:pad4 objects objectsP
set pad4=0000!%1%!
set %2=!pad4:~-4!
exit /b
:pad6
set pad4=000000!%1%!
set %2=!pad4:~-6!
exit /b
:help
echo(%~1
echo(
echo(Usage:
echo(txt2pdf.bat inFile outFile [/A4^|/A3^|/Letter] [/T:n] [/F:n] [/L]
echo(
echo( inFile Path of the source text file.
echo( outFile Path of the destination PDF file.
echo(
echo( /A4 Page size A4. (default)
echo( /A3 Page size A3.
echo( /Letter Page size Letter.
echo(
echo( /T:n Tab width of n spaces. (default 8)
echo( /F:n Font size of n points. (default 10)
echo( /L Orientation Landscape. (default Portrait)
echo(
exit /b