Giter Site home page Giter Site logo

paps's Introduction

About

paps is a command line program for converting Unicode text encoded in UTF-8 to postscript and pdf by using pango.

Installation instructions

See file:INSTALL.md

Example

Here is the output from processing the file misc/small-hello.utf8:

Example image

History

paps was written around 2005 to enable printing of plain text unicode UTF-8 files. It is named by the use of the excellent Pango library (from which it took its first two characters) and outputed postscript (ps, the last two characters). When the initial version was written, there was no simple way of translating the output of pango to postscript outlines, and therefore initially output bitmap fonts in the postscript output.

But I wanted to have resolution independent postscript, and therefore in a subsequent version Ι wrote my own font encoding library in PostScript, by making use of the fact that PostScript is a full programming language. This worked well when sending the result to a PostScript printer, but the use of this library had some serious disadvantages:

  • When converting to pdf you got huge files (two orders of magnitude larger!) since in contrast to PostScript, PDF is not a programming language, and therefore each glyph would be encoded as a PDF path.
  • You couldn't select and copy and paste from the resulting postscript file, since there was no underlying text, only graphic paths.

In the early 2010's the library cairo and its accompanying pangocairo library finally created an easy way of converting pango output to postscript in an idiomatic way. But it took me several years until I finally rewrote paps to make use of them.

But I finally did so and released the resulting version on github in 2015 as version 0.7.0 .

Usage

Run paps --help for getting help.

paps's People

Contributors

bitstreamout avatar dov avatar gberenfield avatar rezso avatar rrthomas avatar tagoh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

paps's Issues

Meson based build doesn't deliver paps.1 man page

Hi,

as far as I understand there is no info in meson.build files how to deliver paps.1 man page. Could you confirm that?

I am updating paps to the newest version, switched to meson and I dont't see paps.1 in the proto area.

Thank you

heap overflow when processing crafted/empty file

Hello,

In gentoo we fixed an heap overflow discovered with fuzzing.
Patch at https://gitweb.gentoo.org/repo/gentoo.git/tree/app-text/paps/files/paps-0.6.8-fix-empty-file.patch
Asan strack trace:

=================================================================                                                                                                                                                                                                              
==30527==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000dfaf at pc 0x0000004e122d bp 0x7ffd8f3dfe90 sp 0x7ffd8f3dfe88                                                                                                                                      
READ of size 1 at 0x60200000dfaf thread T0                                                                                                                                                                                                                                     
    #0 0x4e122c in read_file /tmp/portage/app-text/paps-0.6.8-r1/work/paps-0.6.8/src/paps.c:573:7                                                                                                                                                                              
    #1 0x4e122c in main /tmp/portage/app-text/paps-0.6.8-r1/work/paps-0.6.8/src/paps.c:493                                                                                                                                                                                     
    #2 0x7fd8aff707af in __libc_start_main (/lib64/libc.so.6+0x207af)                                                                                                                                                                                                          
    #3 0x436968 in _start (/usr/bin/paps+0x436968)                                                                                                                                                                                                                             

0x60200000dfaf is located 1 bytes to the left of 4-byte region [0x60200000dfb0,0x60200000dfb4)                                                                                                                                                                                 
allocated by thread T0 here:                                                                                                                                                                                                                                                   
    #0 0x4bdc75 in realloc (/usr/bin/paps+0x4bdc75)                                                                                                                                                                                                                            
    #1 0x7fd8b111c35d in g_realloc (/usr/lib64/libglib-2.0.so.0+0x4e35d)                                                                                                                                                                                                       

SUMMARY: AddressSanitizer: heap-buffer-overflow /tmp/portage/app-text/paps-0.6.8-r1/work/paps-0.6.8/src/paps.c:573 read_file                                                                                                                                                   
Shadow bytes around the buggy address:                                                                                                                                                                                                                                         
  0x0c047fff9ba0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa                                                                                                                                                                                                              
  0x0c047fff9bb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa                                                                                                                                                                                                              
  0x0c047fff9bc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa                                                                                                                                                                                                              
  0x0c047fff9bd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa                                                                                                                                                                                                              
  0x0c047fff9be0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa                                                                                                                                                                                                              
=>0x0c047fff9bf0: fa fa fa fa fa[fa]04 fa fa fa 00 02 fa fa 00 02                                                                                                                                                                                                              
  0x0c047fff9c00: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fa                                                                                                                                                                                                              
  0x0c047fff9c10: fa fa fd fa fa fa 00 00 fa fa 00 00 fa fa 00 00                                                                                                                                                                                                              
  0x0c047fff9c20: fa fa 00 00 fa fa 00 fa fa fa 00 00 fa fa fd fa                                                                                                                                                                                                              
  0x0c047fff9c30: fa fa fd fa fa fa fd fa fa fa 00 00 fa fa 00 00                                                                                                                                                                                                              
  0x0c047fff9c40: fa fa 00 fa fa fa 00 00 fa fa 00 00 fa fa 00 fa                                                                                                                                                                                                              
Shadow byte legend (one shadow byte represents 8 application bytes):                                                                                                                                                                                                           
  Addressable:           00                                                                                                                                                                                                                                                    
  Partially addressable: 01 02 03 04 05 06 07                                                                                                                                                                                                                                  
  Heap left redzone:       fa                                                                                                                                                                                                                                                  
  Heap right redzone:      fb                                                                                                                                                                                                                                                  
  Freed heap region:       fd                                                                                                                                                                                                                                                  
  Stack left redzone:      f1                                                                                                                                                                                                                                                  
  Stack mid redzone:       f2                                                                                                                                                                                                                                                  
  Stack right redzone:     f3                                                                                                                                                                                                                                                  
  Stack partial redzone:   f4                                                                                                                                                                                                                                                  
  Stack after return:      f5                                                                                                                                                                                                                                                  
  Stack use after scope:   f8                                                                                                                                                                                                                                                  
  Global redzone:          f9                                                                                                                                                                                                                                                  
  Global init order:       f6                                                                                                                                                                                                                                                  
  Poisoned by user:        f7                                                                                                                                                                                                                                                  
  Container overflow:      fc                                                                                                                                                                                                                                                  
  Array cookie:            ac                                                                                                                                                                                                                                                  
  Intra object redzone:    bb                                                                                                                                                                                                                                                  
  ASan internal:           fe                                                                                                                                                                                                                                                  
  Left alloca redzone:     ca                                                                                                                                                                                                                                                  
  Right alloca redzone:    cb                                                                                                                                                                                                                                                  
==30527==ABORTING

FreeBSD: 0.8.0 fails to build (autoreconf)

Hello,

Trying to update FreeBSD paps port but getting error:

In file included from format_from_dict.cc:23:
./format_from_dict.h:30:23: error: no template named 'variant' in namespace 'std'
using scalar_t = std::variant<int, std::string, double, std::time_t>;
                 ~~~~~^
./format_from_dict.h:31:38: error: use of undeclared identifier 'scalar_t'
using dict_t = std::map<std::string, scalar_t>;
                                     ^
./format_from_dict.h:36:30: error: unknown type name 'dict_t'
                             dict_t dict);
                             ^
format_from_dict.cc:28:32: error: unknown type name 'scalar_t'
static string scalar_to_string(scalar_t scalar,
                               ^
format_from_dict.cc:65:25: error: unknown type name 'dict_t'
                        dict_t dict)
                        ^
--- paps-paps.o ---
In file included from paps.cc:42:
./format_from_dict.h:30:23: error: no template named 'variant' in namespace 'std'
using scalar_t = std::variant<int, std::string, double, std::time_t>;
                 ~~~~~^
./format_from_dict.h:31:38: error: use of undeclared identifier 'scalar_t'
using dict_t = std::map<std::string, scalar_t>;
                                     ^
./format_from_dict.h:36:30: error: unknown type name 'dict_t'
                             dict_t dict);
                             ^
--- paps-format_from_dict.o ---

Any hints on why this build error happens?

Thanks,

Full log: https://people.freebsd.org/~eduardo/logs/paps/paps-0.8.0.log
PR: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=270515

FreeBSD: fails to build on i386

0.8.0 fails to build on i386 (meson):
Don't have results for armv6, armv7 and other 32bit archs.

Full log: https://people.freebsd.org/~eduardo/logs/paps/124i386_paps-0.8.0.log

===>  Configuring for paps-0.8.0
The Meson build system
Version: 1.0.1
Source dir: /wrkdirs/usr/ports/print/paps/work/paps-0.8.0
Build dir: /wrkdirs/usr/ports/print/paps/work/paps-0.8.0/_build
Build type: native build
Project name: paps
Project version: 0.8.0
C compiler for the host machine: cc (clang 13.0.0 "FreeBSD clang version 13.0.0 ([email protected]:llvm/llvm-project.git llvmorg-13.0.0-0-gd7b669b3a303)")
C linker for the host machine: cc ld.lld 13.0.0
C++ compiler for the host machine: c++ (clang 13.0.0 "FreeBSD clang version 13.0.0 ([email protected]:llvm/llvm-project.git llvmorg-13.0.0-0-gd7b669b3a303)")
C++ linker for the host machine: c++ ld.lld 13.0.0
Host machine cpu family: x86
Host machine cpu: i386

<snip>

paps 0.8.0

  User defined options
    buildtype : release
    infodir   : share/info
    mandir    : man
    prefix    : /usr/local
    strip     : True
    b_colorout: never

<snip>

In file included from ../src/format_from_dict.h:25:
In file included from /usr/include/c++/v1/string:522:
In file included from /usr/include/c++/v1/algorithm:653:
In file included from /usr/include/c++/v1/functional:495:
In file included from /usr/include/c++/v1/__functional/bind_front.h:14:
In file included from /usr/include/c++/v1/__functional/perfect_forward.h:14:
/usr/include/c++/v1/tuple:1189:5: error: static_assert failed due to requirement 'value != __ambiguous' "type occurs more than once in type list"
    static_assert(value != __ambiguous, "type occurs more than once in type list");
    ^             ~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/v1/tuple:1201:14: note: in instantiation of template class 'std::__find_detail::__find_exactly_one_checked<int, int, std::string, double, int>' requested here
    : public __find_detail::__find_exactly_one_checked<_T1, _Args...> {
             ^
/usr/include/c++/v1/variant:1470:30: note: in instantiation of template class 'std::__find_exactly_one_t<int, int, std::string, double, int>' requested here
  return __holds_alternative<__find_exactly_one_t<_Tp, _Types...>::value>(__v);
                             ^
../src/format_from_dict.cc:38:7: note: in instantiation of function template specialization 'std::holds_alternative<int, int, std::string, double, int>' requested here
  if (holds_alternative<int>(scalar))
      ^
../src/format_from_dict.cc:52:7: error: no matching function for call to 'holds_alternative'
  if (holds_alternative<time_t>(scalar))
      ^~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/v1/variant:1469:16: note: candidate template ignored: substitution failure [with _Tp = int, _Types = <int, std::string, double, int>]
constexpr bool holds_alternative(const variant<_Types...>& __v) noexcept {
               ^
2 errors generated.
[ 66% 2/3] c++ -Isrc/paps.p -Isrc -I../src -I. -I.. -I/usr/local/include/pango-1.0 -I/usr/local/include -I/usr/local/include/glib-2.0 -I/usr/local/lib/glib-2.0/include -I/usr/local/include/harfbuzz -I/usr/local/include/freetype2 -I/usr/local/include/libpng16 -I/usr/local/include/fribidi -I/usr/local/include/cairo -I/usr/local/include/pixman-1 -fno-color-diagnostics -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -std=c++17 -O3 -O2 -pipe -fstack-protector-strong -fno-strict-aliasing -pthread -D_THREAD_SAFE -MD -MQ src/paps.p/paps.cc.o -MF src/paps.p/paps.cc.o.d -o src/paps.p/paps.cc.o -c ../src/paps.cc
FAILED: src/paps.p/paps.cc.o
c++ -Isrc/paps.p -Isrc -I../src -I. -I.. -I/usr/local/include/pango-1.0 -I/usr/local/include -I/usr/local/include/glib-2.0 -I/usr/local/lib/glib-2.0/include -I/usr/local/include/harfbuzz -I/usr/local/include/freetype2 -I/usr/local/include/libpng16 -I/usr/local/include/fribidi -I/usr/local/include/cairo -I/usr/local/include/pixman-1 -fno-color-diagnostics -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -std=c++17 -O3 -O2 -pipe -fstack-protector-strong -fno-strict-aliasing -pthread -D_THREAD_SAFE -MD -MQ src/paps.p/paps.cc.o -MF src/paps.p/paps.cc.o.d -o src/paps.p/paps.cc.o -c ../src/paps.cc
../src/paps.cc:1400:30: error: no viable overloaded '='
  document_info["num_pages"] = 0;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~
/usr/include/c++/v1/variant:1365:12: note: candidate function not viable: no known conversion from 'int' to 'const std::variant<int, std::string, double, int>' for 1st argument
  variant& operator=(const variant&) = default;
           ^
/usr/include/c++/v1/variant:1366:12: note: candidate function not viable: no known conversion from 'int' to 'std::variant<int, std::string, double, int>' for 1st argument
  variant& operator=(variant&&) = default;
           ^
/usr/include/c++/v1/variant:1377:12: note: candidate template ignored: substitution failure [with _Arg = int, $1 = 0]: no type named 'type' in 'std::invoke_result<std::__variant_detail::__all_overloads<std::__variant_detail::__overload<int, 0>, std::__variant_detail::__overload<std::string, 1>, std::__variant_detail::__overload<double, 2>, std::__variant_detail::__overload<int, 3>>, int, int>'
  variant& operator=(_Arg&& __arg) noexcept(
           ^
../src/paps.cc:1412:33: error: no viable overloaded '='
      document_info["page_idx"] = page_idx;
      ~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~
/usr/include/c++/v1/variant:1365:12: note: candidate function not viable: no known conversion from 'int' to 'const std::variant<int, std::string, double, int>' for 1st argument
(...)

paps dumps core with --columns=0 option

I got the report that paps dumps core with --columns=0 option.
To reproduce,

echo "Something" | paps --columns=0

% echo "Something" | ./paps --columns=0
zsh: done echo "Something" |
zsh: floating point exception (core dumped) ./paps --columns=0

We are applying the following patch so it would be great if this
is also applied by default.

% gdiff -u paps.c.org paps.c
--- paps.c.org 2016-07-20 09:21:33.529764313 +0900
+++ paps.c 2016-07-20 11:15:21.514121049 +0900
@@ -667,6 +667,11 @@
glyph_font_size = pango_font_description_get_size(font_description) / PANGO_S
CALE;
pango_context_set_font_description (pango_context, font_description);

+ if (num_columns == 0) {

  • fprintf(stderr, ("%s: Invalid input: --columns=%d, using default.\n"), g
    get_prgname (), num_columns);
  • num_columns = 1;
  • }
  • if (num_columns == 1)
    total_gutter_width = 0;
    else

Cannot build on ArchLinux

Hi,
Compilation is Ok with meson, but ./configure && make does not work

hubert@xps15al:~/abs/paps-0.8.0 $ LANG=C make
make all-recursive
make[1]: Entering directory '/home/hubert/abs/paps-0.8.0'
Making all in src
make[2]: Entering directory '/home/hubert/abs/paps-0.8.0/src'
g++ -DHAVE_CONFIG_H -I. -I.. -DGETTEXT_PACKAGE='"paps"' -DDATADIR='"/usr/local/share"' -fno-strict-aliasing -Wnested-externs -Wmissing-prototypes -Wstrict-prototypes -Wdeclaration-after-statement -Wimplicit-function-declaration -Wold-style-definition -Wjump-misses-init -Wall -Wextra -Wundef -Wwrite-strings -Wpointer-arith -Wmissing-declarations -Wredundant-decls -Wno-unused-parameter -Wno-missing-field-initializers -Wformat=2 -Wcast-align -Wformat-nonliteral -Wformat-security -Wsign-compare -Wstrict-aliasing -Wshadow -Winline -Wpacked -Wmissing-format-attribute -Wmissing-noreturn -Winit-self -Wmissing-include-dirs -Wunused-but-set-variable -Warray-bounds -Wreturn-type -Wswitch-enum -Wswitch-default -Wduplicated-cond -Wduplicated-branches -Wlogical-op -Wrestrict -Wnull-dereference -Wdouble-promotion -Werror -Wno-suggest-attribute=format -Wno-error=unused-parameter -Wno-error=missing-field-initializers -Wno-format-y2k -I/usr/include/pango-1.0 -I/usr/include/cairo -I/usr/include/freetype2 -I/usr/include/harfbuzz -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/fribidi -I/usr/include/pixman-1 -I/usr/include/libpng16 -I/usr/include/sysprof-6 -pthread -g -O2 -MT paps-paps.o -MD -MP -MF .deps/paps-paps.Tpo -c -o paps-paps.o test -f 'paps.cc' || echo './'paps.cc
cc1plus: warning: command-line option '-Wnested-externs' is valid for C/ObjC but not for C++
cc1plus: warning: command-line option '-Wmissing-prototypes' is valid for C/ObjC but not for C++
cc1plus: warning: command-line option '-Wstrict-prototypes' is valid for C/ObjC but not for C++
cc1plus: warning: command-line option '-Wdeclaration-after-statement' is valid for C/ObjC but not for C++
cc1plus: warning: command-line option '-Wimplicit-function-declaration' is valid for C/ObjC but not for C++
cc1plus: warning: command-line option '-Wold-style-definition' is valid for C/ObjC but not for C++
cc1plus: warning: command-line option '-Wjump-misses-init' is valid for C/ObjC but not for C++
In file included from /usr/include/glib-2.0/glib/giochannel.h:36,
from /usr/include/glib-2.0/glib.h:56,
from /usr/include/glib-2.0/glib/gprintf.h:23,
from /usr/include/glib-2.0/glib/gstdio.h:24,
from paps.cc:23:
paps.cc: In function 'bool copy_pango_parse_enum(GType, const char*, int*, bool, char**)':
/usr/include/glib-2.0/glib/gstring.h:73:31: error: ignoring return value of 'gchar* g_string_free_and_steal(GString*)' declared with attribute 'warn_unused_result' [-Werror=unused-result]
73 | g_string_free_and_steal (str))
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
paps.cc:388:11: note: in expansion of macro 'g_string_free'
388 | g_string_free (s, possible_values ? false : true);
| ^~~~~~~~~~~~~
paps.cc: In function 'char* read_file(FILE*, gchar*)':
/usr/include/glib-2.0/glib/gstring.h:73:31: error: ignoring return value of 'gchar* g_string_free_and_steal(GString*)' declared with attribute 'warn_unused_result' [-Werror=unused-result]
73 | g_string_free_and_steal (str))
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
paps.cc:1047:3: note: in expansion of macro 'g_string_free'
1047 | g_string_free (inbuf, false);
| ^~~~~~~~~~~~~
paps.cc: In function 'std::string get_date()':
/usr/include/glib-2.0/glib/gstring.h:73:31: error: ignoring return value of 'gchar* g_string_free_and_steal(GString*)' declared with attribute 'warn_unused_result' [-Werror=unused-result]
73 | g_string_free_and_steal (str))
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
paps.cc:1674:7: note: in expansion of macro 'g_string_free'
1674 | g_string_free(inbuf, false);
| ^~~~~~~~~~~~~
/usr/include/glib-2.0/glib/gstring.h:73:31: error: ignoring return value of 'gchar* g_string_free_and_steal(GString*)' declared with attribute 'warn_unused_result' [-Werror=unused-result]
73 | g_string_free_and_steal (str))
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
paps.cc:1683:5: note: in expansion of macro 'g_string_free'
1683 | g_string_free(inbuf, false);
| ^~~~~~~~~~~~~
cc1plus: all warnings being treated as errors
make[2]: *** [Makefile:454: paps-paps.o] Error 1
make[2]: Leaving directory '/home/hubert/abs/paps-0.8.0/src'
make[1]: *** [Makefile:502: all-recursive] Error 1
make[1]: Leaving directory '/home/hubert/abs/paps-0.8.0'
make: *** [Makefile:387: all] Error 2

svg output not displayed correctly.

In 20151223 version of paps, I got the following bug report.

Svg output from paps is not displayed correctly. Only the last page is
visible. To reproduce, run any paps command with --format=svg option.

% LANG=C
% man paps | col -xb | paps --format=svg > out.svg

Then check out.svg through firefox, I can see only last page.

I'm not sure about how pages should work with svg format...

--header issues

Thank you for the very useful programme.

Ability to configure the header would help a lot, that is, unless you yourself choose to remove the date and the "Page" strings.

The "Page" string ruins a non-English conversion and don't you think it's redundant in the first place?

The date string ruins any conversion.

header

error: cannot recognize version marker

I get this error:

$ mupdf Friday-June-24-2022-07\:51\:12.pdf 
error: cannot recognize version marker
warning: trying to repair broken xref
warning: repairing PDF document

PDF was generated with options: "--format" "--landscape" "--title" "--header"

I hope this may be repaired as Emacs cannot read these files.

Separate processing messages from standard output

I am observing that I will get the line Got 1 pages if I redirect output to PDF like following:

$ paps --markup my-pango.txt > my-pango.pdf

And such PDF file is invalid and cannot be opened.

If I however, do it this way, then it will work:

$ paps --markup my-pango.txt -o my-pango.pdf

It is necessary to separate processing messages from standard output. Please consider separating processing messages maybe to be printed to standard error, instead of to standard output. As in that case, the output by redirection would work, and message would be shown to user, and not go into PDF file.

In that case user would need to do something like following to get the same error:

$ paps --markup my-pango.txt > my-pango.pdf 2>&1

As that would be explicit, it would tell to program to put even error messages to file.

cpi option forces printing line breaks anywhere

In 20151223 version of paps, I got the following bug report.

After using --cpi option, the output of paps looks as if --wrap=char option
was used. Line breaks are inserted even in the middle of words. This cannot
be overwritten even by using --wrap=word option.
According to man page, cpi should be an alternative way to specify font size.
The font size is changed, but line breaking behavior is different.

To reproduce this issue, use any English text as input to following command:

% LANG=C
% man paps | col -xb | paps --cpi=8 > out.ps

If I see this out.ps through ghostscript, I can see line breaking in the
middle of words. Ex, the word "creating" is wrapped between "cre" and "ating".

Merge with pango

I think paps should be moved into pango itself. What do you think?

Cannot run ./configure in /src dir

Following the instructions in INSTALL, I 'cd' to paps/src and entered the command

./configure && make && make install

That returned the error

-bash: ./configure: No such file or directory

Using a Raspbian GNU/Linux 11 (bullseye).

I used apt-get to install it originally but the most recent version they seem to have at apt-get is 0.6.8-7.1

Add a wrap-around marker for wrapped around lines

paps should support character wrap around and placing a "wrap-around" character, e.g. ⤶ in the margin when the line is wrapped. (If the line is an RTL line, then the character ⤷ may be placed in the left margin).

--g-fatal-warnings option should remove "REAL" from the last arguments

In 20151223 version of paps, I got the following issue.

paps -h and paps's man pages describe '--g-fatal-warnings' differently

paps.1 man page haven't described about '--g-fatal-warnings' yet but
we are applying the following patch for paps.1 so this issue was raised.

https://github.com/dov/paps/pull/18/commits/4be7c77077cefedf9b000a85cdaf8621700f577a

I checked that paps.c and it looks to me that updated man page is
right because do_fatal_warnings is defined as gboolean. So I think
paps.c should remove "REAL" from the last arguments.

% ./paps --help |& grep g-fatal-warnings
--g-fatal-warnings=REAL Set glib fatal warnings
% grep do_fatal_warnings paps.c
gboolean do_fatal_warnings = FALSE;
{"g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &do_fatal_warnings,
if (do_fatal_warnings)
% gdiff -u paps.c.org paps.c
--- paps.c.org 2016-07-20 09:21:33.529764313 +0900
+++ paps.c 2016-07-20 09:22:32.614399477 +0900
@@ -510,7 +510,7 @@
N_("Stretch characters in y-direction to fill lines."), NULL},
*/
{"g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &do_fatal_warnings,

  • N_("Set glib fatal warnings"), "REAL"},
    
  • N_("Set glib fatal warnings"), NULL},
    
    {NULL}

fonts sizes are still weird with --markup

The default font is not applied when using --markup. Trying input such as the below with and without the --markup option the result with markup seems off not by just font size.

markup.txt:

Markup default font <span foreground="blue">Markup blue</span> <span font="Monospace 12">Monospace 12</span>

Scaling is wrong

The scaling of the font is wrong in the cairo branch. The text is too big.

paps.c:283:3: error: ‘pango_parse_enum’ is deprecated [-Werror=deprecated-declarations]

paps refuses to build with pango-1.42.4:

(CDPATH="${ZSH_VERSION+.}:" && cd . && /bin/sh /var/tmp/portage/app-text/paps-0.7.1/work/paps-0.7.1/config/missing autoheader)
configure.ac:14: warning: AC_COMPILE_IFELSE was called before AC_USE_SYSTEM_EXTENSIONS
../../lib/autoconf/specific.m4:314: AC_GNU_SOURCE is expanded from...
configure.ac:14: the top level
rm -f stamp-h1
touch config.h.in
cd . && /bin/sh ./config.status config.h
config.status: creating config.h
config.status: config.h is unchanged
make  all-recursive
make[1]: Entering directory '/var/tmp/portage/app-text/paps-0.7.1/work/paps-0.7.1'
Making all in src
make[2]: Entering directory '/var/tmp/portage/app-text/paps-0.7.1/work/paps-0.7.1/src'
x86_64-pc-linux-gnu-gcc -DHAVE_CONFIG_H -I. -I..  -DGETTEXT_PACKAGE='"paps"' -DDATADIR='"/usr/share"'  -fno-strict-aliasing -Wnested-externs -Wmissing-prototypes -Wstrict-prototypes -Wdeclaration-after-statement -Wimplicit-function-declaration -Wold-style-definition -Wjump-misses-init -Wall -Wextra -Wundef -Wwrite-strings -Wpointer-arith -Wmissing-declarations -Wredundant-decls -Wno-unused-parameter -Wno-missing-field-initializers -Wformat=2 -Wcast-align -Wformat-nonliteral -Wformat-security -Wsign-compare -Wstrict-aliasing -Wshadow -Winline -Wpacked -Wmissing-format-attribute -Wmissing-noreturn -Winit-self -Wmissing-include-dirs -Wunused-but-set-variable -Warray-bounds -Wreturn-type -Wswitch-enum -Wswitch-default -Wduplicated-cond -Wduplicated-branches -Wlogical-op -Wrestrict -Wnull-dereference -Wdouble-promotion -Werror -Wno-suggest-attribute=format -Wno-error=unused-parameter -Wno-error=missing-field-initializers -Wno-format-y2k -I/usr/include/pango-1.0 -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/libdrm -I/usr/include/libpng16 -I/usr/include/pango-1.0 -I/usr/include/harfbuzz -I/usr/include/pango-1.0 -I/usr/include/fribidi -I/usr/lib64/libffi-3.3_rc2/include -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/uuid -I/usr/include/freetype2 -O2 -pipe -march=ivybridge -mtune=native -ftree-vectorize -c -o paps-paps.o `test -f 'paps.c' || echo './'`paps.c
paps.c: In function ‘parse_enum’:
paps.c:283:3: error: ‘pango_parse_enum’ is deprecated [-Werror=deprecated-declarations]
   ret = pango_parse_enum (type,
   ^~~
In file included from /usr/include/pango-1.0/pango/pango.h:46,
                 from paps.c:23:
/usr/include/pango-1.0/pango/pango-utils.h:63:10: note: declared here
 gboolean pango_parse_enum     (GType       type,
          ^~~~~~~~~~~~~~~~
paps.c: At top level:
paps.c:427:1: error: function declaration isn’t a prototype [-Werror=strict-prototypes]
 get_encoding()
 ^~~~~~~~~~~~
paps.c: In function ‘get_encoding’:
paps.c:427:1: error: old-style function definition [-Werror=old-style-definition]
paps.c: In function ‘main’:
paps.c:540:7: error: unused variable ‘header_sep’ [-Werror=unused-variable]
   int header_sep = 20;
       ^~~~~~~~~~
paps.c:715:6: error: this condition has identical branches [-Werror=duplicated-branches]
   if (do_draw_header)
      ^
paps.c: In function ‘read_file’:
paps.c:821:20: error: unused variable ‘ibleft’ [-Werror=unused-variable]
       gsize iblen, ibleft, oblen;
                    ^~~~~~
paps.c: In function ‘split_text_into_paragraphs’:
paps.c:983:38: error: implicit declaration of function ‘wcwidth’ [-Werror=implicit-function-declaration]
                           gssize w = wcwidth (wtext[i]);
                                      ^~~~~~~
paps.c:983:38: error: nested extern declaration of ‘wcwidth’ [-Werror=nested-externs]
paps.c: At top level:
paps.c:1363:1: error: no previous prototype for ‘get_date’ [-Werror=missing-prototypes]
 get_date(char *date, int maxlen)
 ^~~~~~~~
paps.c: In function ‘draw_page_header_line_to_page’:
paps.c:1422:11: error: unused variable ‘line_pos’ [-Werror=unused-variable]
   gdouble line_pos;
           ^~~~~~~~
paps.c:1420:18: error: unused variable ‘date’ [-Werror=unused-variable]
   gchar *header, date[256];
                  ^~~~
cc1: all warnings being treated as errors
make[2]: *** [Makefile:445: paps-paps.o] Error 1
make[2]: Leaving directory '/var/tmp/portage/app-text/paps-0.7.1/work/paps-0.7.1/src'
make[1]: *** [Makefile:401: all-recursive] Error 1
make[1]: Leaving directory '/var/tmp/portage/app-text/paps-0.7.1/work/paps-0.7.1'
make: *** [Makefile:342: all] Error 2

Line 1470 of paps.cc is causing problems with output passed to ps2pdf

Hi

Building paps from HEAD:

Line 1470 of src/paps.cc (print("Got`` {} pages\n", num_pages);) is putting that line, uncommented, at the head of the ps output, which leads ps2pdf to emit an error (Error: /undefined in Got). So the test case echo 'test' | ./src/paps | ps2pdf - test.pdf fails.

Emoji alignment incorrect

                <span font="DejaVu Sans 30" underline="double">⭐ Header</span>

If I process above as Pango markup, the start get displaced down.

Cannot build on Debian

$ make
make  all-recursive
make[1]: Entering directory '/home/data1/protected/Programming/git/paps'
Making all in src
make[2]: Entering directory '/home/data1/protected/Programming/git/paps/src'
g++ -DHAVE_CONFIG_H -I. -I..  -DGETTEXT_PACKAGE='"paps"' -DDATADIR='"/package/tools/paps/share"'   -pthread -I/usr/include/pango-1.0 -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/fribidi -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/harfbuzz -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/uuid -I/usr/include/freetype2 -I/usr/include/libpng16  -g -O2 -MT paps-paps.o -MD -MP -MF .deps/paps-paps.Tpo -c -o paps-paps.o `test -f 'paps.cc' || echo './'`paps.cc
In file included from paps.cc:42:
format_from_dict.h:30:23: error: ‘variant’ in namespace ‘std’ does not name a template type
   30 | using scalar_t = std::variant<int, std::string, double, std::time_t>;
      |                       ^~~~~~~
format_from_dict.h:30:18: note: ‘std::variant’ is only available from C++17 onwards
   30 | using scalar_t = std::variant<int, std::string, double, std::time_t>;
      |                  ^~~
format_from_dict.h:31:38: error: ‘scalar_t’ was not declared in this scope
   31 | using dict_t = std::map<std::string, scalar_t>;
      |                                      ^~~~~~~~
format_from_dict.h:31:46: error: template argument 2 is invalid
   31 | using dict_t = std::map<std::string, scalar_t>;
      |                                              ^
format_from_dict.h:31:46: error: template argument 4 is invalid
format_from_dict.h:36:30: error: ‘dict_t’ has not been declared
   36 |                              dict_t dict);
      |                              ^~~~~~
paps.cc:160:3: error: ‘dict_t’ does not name a type; did you mean ‘wint_t’?
  160 |   dict_t document_info;
      |   ^~~~~~
      |   wint_t
paps.cc:221:45: error: ‘dict_t’ has not been declared
  221 |                                             dict_t&           document_info,
      |                                             ^~~~~~
paps.cc:227:45: error: ‘dict_t’ has not been declared
  227 |                                             dict_t& document_info);
      |                                             ^~~~~~
paps.cc: In function ‘int output_pages(cairo_surface_t*, cairo_t*, GList*, PageLayout*, PangoContext*)’:
paps.cc:1396:3: error: ‘dict_t’ was not declared in this scope; did you mean ‘wint_t’?
 1396 |   dict_t document_info;
      |   ^~~~~~
      |   wint_t
paps.cc:1399:36: error: ‘document_info’ was not declared in this scope; did you mean ‘build_document_info’?
 1399 |   build_document_info(page_layout, document_info);
      |                                    ^~~~~~~~~~~~~
      |                                    build_document_info
paps.cc: At global scope:
paps.cc:1700:31: error: ‘dict_t’ has not been declared
 1700 |                               dict_t&          document_info,
      |                               ^~~~~~
paps.cc:1841:21: error: ‘dict_t’ has not been declared
 1841 |                     dict_t& document_info)
      |                     ^~~~~~
paps.cc: In function ‘void build_document_info(PageLayout*, int&)’:
paps.cc:1843:29: error: assignment of read-only location ‘"filename"[document_info]’
 1843 |   document_info["filename"] = page_layout->filename;
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
paps.cc:1844:25: error: assignment of read-only location ‘"path"[document_info]’
 1844 |   document_info["path"] = page_layout->filename_path;
      |   ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
paps.cc:1848:26: error: assignment of read-only location ‘"mtime"[document_info]’
 1848 |   document_info["mtime"] = (time_t)stat_buf.st_mtime;
      |                          ^
paps.cc:1849:24: error: assignment of read-only location ‘"now"[document_info]’
 1849 |   document_info["now"] = time(nullptr);
      |   ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
paps.cc:1851:16: error: ‘struct PageLayout’ has no member named ‘document_info’
 1851 |   page_layout->document_info["num_pages"] = page_layout->num_pages;
      |                ^~~~~~~~~~~~~
make[2]: *** [Makefile:451: paps-paps.o] Error 1
make[2]: Leaving directory '/home/data1/protected/Programming/git/paps/src'
make[1]: *** [Makefile:499: all-recursive] Error 1
make[1]: Leaving directory '/home/data1/protected/Programming/git/paps'
make: *** [Makefile:384: all] Error 2

If a Pango markup `<span>` spans two lines, `paps` throws two warnings and ignore that `<span>`

With paps 0.8.0, executing paps --markup on the following text with Pango markup:

<span foreground="#006633">something
</span>
<span foreground="#aa6633">something else</span>

throws two warnings:

(paps:446639): Pango-WARNING **: 17:41:06.490: pango_layout_set_markup_with_accel: Error on line 1 char 53: Element “markup” was closed, but the currently open element is “span”

(paps:446639): Pango-WARNING **: 17:41:06.490: pango_layout_set_markup_with_accel: Error on line 1 char 15: Element “span” was closed, but the currently open element is “markup”

and the resulting PostScript file contains only the second line “something else”.

With paps 0.7.1, there is no warning and we get both lines in the PostScript file.

the --stretch-chars option is broken

Testing the --stretch-chars option there seems to be no effect on the output. Assuming I need to combine it with a --lpi=4 or similar value to stretch the lines, the characters are not streched along, so 'paps --lpi=4' and 'paps --lpi=4 --stretch-chars' produces the same output.

Add option --markup-monospace

The line breaking algorithm used when doing CHAR wrapping leaves hyphens in the text, and is in general not appropriate for highlighted source code wrapping.

I suggest to add a new option --markup-monospace that will use markup for color coding, but still do "hard" line wrapping inside paps.

memory leak

ago@willoughby /tmp $ echo "foo" > foo.txt && paps foo.txt 
foo foo.txt                                                                                                                                                                                                                                                                   
%!PS-Adobe-3.0                                                                                                                                                                                                                                                                
%%Title: foo.txt                                                                                                                                                                                                                                                              
%%Creator: paps version 0.6.7 by Dov Grobgeld                                                                                                                                                                                                                                 
%%Pages: (atend)                                                                                                                                                                                                                                                              
%%BoundingBox: 0 0 595 841                                                                                                                                                                                                                                                    
%%BeginProlog                                                                                                                                                                                                                                                                 
%%Orientation: Portrait                                                                                                                                                                                                                                                       
/papsdict 1 dict def                                                                                                                                                                                                                                                          
papsdict begin                                                                                                                                                                                                                                                                

/inch {72 mul} bind def                                                                                                                                                                                                                                                       
/mm {1 inch 25.4 div mul} bind def                                                                                                                                                                                                                                            

% override setpagedevice if it is not defined                                                                                                                                                                                                                                 
/setpagedevice where {                                                                                                                                                                                                                                                        
    pop % get rid of its dictionary                                                                                                                                                                                                                                           
    /setpagesize {                                                                                                                                                                                                                                                            
       3 dict begin                                                                                                                                                                                                                                                           
         /pageheight exch def                                                                                                                                                                                                                                                 
         /pagewidth exch def                                                                                                                                                                                                                                                  
         /orientation 0 def                                                                                                                                                                                                                                                   
         % Exchange pagewidth and pageheight so that pagewidth is bigger                                                                                                                                                                                                      
         pagewidth pageheight gt {                                                                                                                                                                                                                                            
             pagewidth                                                                                                                                                                                                                                                        
             /pagewidth pageheight def                                                                                                                                                                                                                                        
             /pageheight exch def                                                                                                                                                                                                                                             
             /orientation 3 def                                                                                                                                                                                                                                               
         } if                                                                                                                                                                                                                                                                 
         2 dict                                                                                                                                                                                                                                                               
         dup /PageSize [pagewidth pageheight] put                                                                                                                                                                                                                             
         dup /Orientation orientation put                                                                                                                                                                                                                                     
         setpagedevice                                                                                                                                                                                                                                                        
       end                                                                                                                                                                                                                                                                    
    } def                                                                                                                                                                                                                                                                     
}                                                                                                                                                                                                                                                                             
{                                                                                                                                                                                                                                                                             
    /setpagesize { pop pop } def                                                                                                                                                                                                                                              
} ifelse                                                                                                                                                                                                                                                                      
/duplex {                                                                                                                                                                                                                                                                     
    statusdict /setduplexmode known 
    { statusdict begin setduplexmode end } {pop} ifelse
} def
/tumble {
    statusdict /settumble known
   { statusdict begin settumble end } {pop} ifelse
} def
% Turn the page around
/turnpage {
  90 rotate
  0 pageheight neg translate
} def
% User settings
/pagewidth 595 def
/pageheight 841 def
pagewidth pageheight setpagesize
/column_width 523 def
/bodyheight 769 def
/lmarg 36 def
/ytop 805 def
/do_separation_line true def
/do_landscape false def
/do_tumble true def
/do_duplex true def
% Procedures to translate position to first and second column
/lw 20 def % whatever
/setnumcolumns {
    /numcolumns exch def
    /firstcolumn { /xpos lmarg def /ypos ytop def} def
    /nextcolumn { 
      do_separation_line {
          xpos column_width add gutter_width 2 div add % x start
           ytop lw add moveto              % y start
          0 bodyheight lw add neg rlineto 0 setlinewidth stroke
      } if
      /xpos xpos column_width add gutter_width add def 
      /ypos ytop def
    } def
} def

1 setnumcolumns
/showline {
    /y exch def
    /s exch def
    xpos y moveto 
    column_width 0 rlineto stroke
    xpos y moveto /Helvetica findfont 20 scalefont setfont s show
} def
/paps_bop {  % Beginning of page definitions
    papsdict begin
    gsave
    do_landscape {turnpage} if 
    % ps2pdf gets wrong orientation without this!
    /Helvetica findfont setfont 100 100 moveto ( ) show
    firstcolumn
    end
} def

/paps_eop {  % End of page cleanups
    grestore    
} def
%%BeginProlog
/papsdict 1 dict def
papsdict begin

/conicto {
    /to_y exch def
    /to_x exch def
    /conic_cntrl_y exch def
    /conic_cntrl_x exch def
    currentpoint
    /p0_y exch def
    /p0_x exch def
    /p1_x p0_x conic_cntrl_x p0_x sub 2 3 div mul add def
    /p1_y p0_y conic_cntrl_y p0_y sub 2 3 div mul add def
    /p2_x p1_x to_x p0_x sub 1 3 div mul add def
    /p2_y p1_y to_y p0_y sub 1 3 div mul add def
    p1_x p1_y p2_x p2_y to_x to_y curveto
} bind def
/start_ol { gsave } bind def
/end_ol { closepath fill grestore } bind def
/draw_char { fontdict begin gsave 0.001000 dup scale last_x last_y translate load exec end grestore} def
/goto_xy { fontdict begin /last_y exch def /last_x exch def end } def
/goto_x { fontdict begin /last_x exch def end } def
/fwd_x { fontdict begin /last_x exch last_x add def end } def
/c /curveto load def
/x /conicto load def
/l /lineto load def
/m /moveto load def
end
/paps_exec {
  1 dict begin
  /ps exch def
  /len ps length def
  /pos 0 def

  % Loop over all the characters of the string
  {
    pos len eq {exit} if

    % Get character at pos
    /ch ps pos 1 getinterval def

    % check for +
    (+) ch eq {
      /pos 1 pos add def
      /xp ps pos 8 getinterval cvi def
      /yp ps pos 8 add 8 getinterval cvi def
      /pos 16 pos add def
      papsdict begin xp yp goto_xy end
    } {
      (*) ch eq {
        /pos 1 pos add def
        /xp ps pos 8 getinterval cvi def
        /pos 8 pos add def
        papsdict begin xp goto_x end
      } { (>) ch eq {
          /pos 1 pos add def
          /xp ps pos 4 getinterval cvi def
          /pos 4 pos add def
          papsdict begin xp 2 mul fwd_x end
        } { (-) ch eq {
            /pos 1 pos add def
            /xp ps pos 4 getinterval cvi def
            /pos 4 pos add def
            papsdict begin xp neg 2 mul fwd_x end
          } {
              % Must be a 3 char sym. Load and exec
              /name ps pos 3 getinterval def
              papsdict begin name draw_char end
              /pos 3 pos add def
            } ifelse
          } ifelse
        } ifelse
    } ifelse
  } loop
  end
} def
/fontdict 1 dict def
papsdict begin fontdict begin
/AAA { start_ol
6192 9144 m
6192 8280 l
4980 8280 l
4406 8280 4182 8032 x
3960 7785 3960 7156 x
3960 6552 l
6192 6552 l
6192 5688 l
3960 5688 l
3960 0 l
2880 0 l
2880 5688 l
1152 5688 l
1152 6552 l
2880 6552 l
2880 7027 l
2880 8115 3372 8629 x
3866 9144 4910 9144 x
6192 9144 l
7272 fwd_x
end_ol
 } def
/BAA { start_ol
3596 5760 m
2782 5760 2362 5133 x
1944 4506 1944 3276 x
1944 2050 2362 1420 x
2782 792 3596 792 x
4417 792 4836 1420 x
5256 2050 5256 3276 x
5256 4506 4836 5133 x
4417 5760 3596 5760 x
3596 6696 m
4961 6696 5684 5817 x
6408 4939 6408 3276 x
6408 1606 5686 731 x
4966 -144 3596 -144 x
2233 -144 1512 731 x
792 1606 792 3276 x
792 4939 1512 5817 x
2233 6696 3596 6696 x
7272 fwd_x
end_ol
 } def
end end
%%EndPrologue
%%EndPrologue
%%Page: 1 1
paps_bop
(+   36000  791032AAABAABAA)paps_exec
paps_eop
showpage
%%Pages: 1
%%Trailer
%%EOF

=================================================================
==20494==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 2048 byte(s) in 3 object(s) allocated from:
    #0 0x4bdc75 in realloc (/usr/local/bin/paps+0x4bdc75)
    #1 0x7f99d8d7d14a  (/usr/lib64/libfontconfig.so.1+0x1c14a)

Indirect leak of 2176 byte(s) in 68 object(s) allocated from:
    #0 0x4bdaab in __interceptor_calloc (/usr/local/bin/paps+0x4bdaab)
    #1 0x7f99d8d7d8b8  (/usr/lib64/libfontconfig.so.1+0x1c8b8)

Indirect leak of 1856 byte(s) in 58 object(s) allocated from:
    #0 0x4bd932 in __interceptor_malloc (/usr/local/bin/paps+0x4bd932)
    #1 0x7f99d8d6c52f  (/usr/lib64/libfontconfig.so.1+0xb52f)

Indirect leak of 1333 byte(s) in 96 object(s) allocated from:
    #0 0x4bd932 in __interceptor_malloc (/usr/local/bin/paps+0x4bd932)
    #1 0x7f99d92a12c9 in __strdup (/lib64/libc.so.6+0x812c9)

Indirect leak of 864 byte(s) in 27 object(s) allocated from:
    #0 0x4bdaab in __interceptor_calloc (/usr/local/bin/paps+0x4bdaab)
    #1 0x7f99d8d7cde4  (/usr/lib64/libfontconfig.so.1+0x1bde4)

Indirect leak of 96 byte(s) in 2 object(s) allocated from:
    #0 0x4bd932 in __interceptor_malloc (/usr/local/bin/paps+0x4bd932)
    #1 0x7f99d8d77b0d in FcLangSetCreate (/usr/lib64/libfontconfig.so.1+0x16b0d)

Indirect leak of 64 byte(s) in 2 object(s) allocated from:
    #0 0x4bdaab in __interceptor_calloc (/usr/local/bin/paps+0x4bdaab)
    #1 0x7f99d8d7cc64  (/usr/lib64/libfontconfig.so.1+0x1bc64)

Indirect leak of 32 byte(s) in 1 object(s) allocated from:
    #0 0x4bd932 in __interceptor_malloc (/usr/local/bin/paps+0x4bd932)
    #1 0x7f99d8d7b842 in FcMatrixCopy (/usr/lib64/libfontconfig.so.1+0x1a842)

SUMMARY: AddressSanitizer: 8469 byte(s) leaked in 257 allocation(s).

To reproduce just compile it with -fsanitize=address which includes the memleak.

build on cygwin?

I tried to build paps on cygwin. File INSTALL mentions a configure script but there is none. INSTALL.md advises to use meson and mentions a dependency to fmtlib (pango and cairo dependencies could also be mentioned) - however, fmtlib does not have any build instructions at all.

Add support for markdown rendering

With the exception of source code and tables, it should be pretty easy to support MarkDown mode. Tables also shouldn't be too difficult to support. Source code would requires an external library or just be rendered in a fixed font.

Typos in README.md?

From README.md:

plis is a command line program for for converting Unicode text

  • What might "plis" be? An old name or a future name of paps?
  • There are two consecutive "for"s.

Printing two-sided is hardcoded in output PostScript files.

In 20151223 version of paps, I got the following issue.

There is an issue with physically printing PostScript files one-sided or
two-sided. It seems to me that currently this information is hard-coded in
PostScript documents generated by paps - I was not able to configure this in
the print dialog.
The problematic part in all output ps files from paps seems to be this one:

%%BeginSetup
%%IncludeFeature: *Duplex DuplexTumble
%%EndSetup

Right now, all the documents are printed two-sided, short edge. After
removing the IncludeFeature line, I was able to configure the print
preferences as I wanted to.

We are applying the following patch so it would be great if this
is also applied by default.

gdiff -u paps.c.org paps.c
--- paps.c.org 2016-07-20 09:21:33.529764313 +0900
+++ paps.c 2016-07-20 10:41:12.232506530 +0900
@@ -678,16 +678,16 @@
page_width = page_height;
page_height = tmp;
if (do_tumble < 0)

  •    do_tumble = TRUE;
    
  •    do_tumble = FALSE;
     if (do_duplex < 0)
    
  •    do_duplex = TRUE;
    
  •    do_duplex = FALSE;
    
    }
    else
    {
    if (do_tumble < 0)
  •    do_tumble = TRUE;
    
  •    do_tumble = FALSE;
     if (do_duplex < 0)
    
  •    do_duplex = TRUE;
    
  •    do_duplex = FALSE;
    
    }

Make the printed header and footer configurable

Currently the header option creates a fixed default header. This header should be made user selectable by allowing specifying pango markup for the top left, center, and right of the page. In addition support should be added for a page footer.

pango_attr_insert_hyphens_new

Hello,

run

./autogen.sh
./configure
make

result:

make[2]: Entering directory '/home/konstantin/temp/tp/paps/src'
gcc -DHAVE_CONFIG_H -I. -I..  -DGETTEXT_PACKAGE='"paps"' -DDATADIR='"/usr/local/share"'   -I/usr/include/pango-1.0 -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/pango-1.0 -I/usr/include/harfbuzz -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/freetype2 -I/usr/include/libpng16 -g -O2 -MT paps-paps.o -MD -MP -MF .deps/paps-paps.Tpo -c -o paps-paps.o `test -f 'paps.c' || echo './'`paps.c
paps.c: In function ‘split_text_into_paragraphs’:
paps.c:988:33: warning: implicit declaration of function ‘pango_attr_insert_hyphens_new’; did you mean ‘pango_attr_gravity_hint_new’? [-Wimplicit-function-declaration]
   pango_attr_list_insert(attrs, pango_attr_insert_hyphens_new(page_layout->do_show_hyphens));
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                 pango_attr_gravity_hint_new
paps.c:988:33: warning: passing argument 2 of ‘pango_attr_list_insert’ makes pointer from integer without a cast [-Wint-conversion]
In file included from /usr/include/pango-1.0/pango/pango.h:25:0,
                 from paps.c:23:
/usr/include/pango-1.0/pango/pango-attributes.h:534:20: note: expected ‘PangoAttribute * {aka struct _PangoAttribute *}’ but argument is of type ‘int’
 void               pango_attr_list_insert        (PangoAttrList  *list,
                    ^~~~~~~~~~~~~~~~~~~~~~
mv -f .deps/paps-paps.Tpo .deps/paps-paps.Po
gcc  -I/usr/include/pango-1.0 -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/pango-1.0 -I/usr/include/harfbuzz -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/freetype2 -I/usr/include/libpng16 -g -O2   -o paps paps-paps.o  -lpangocairo-1.0 -lcairo -lpangoft2-1.0 -lpango-1.0 -lgobject-2.0 -lglib-2.0 -lfontconfig -lfreetype   
paps-paps.o: In function `split_text_into_paragraphs':
/home/konstantin/temp/tp/paps/src/paps.c:988: undefined reference to `pango_attr_insert_hyphens_new'
collect2: error: ld returned 1 exit status

As I understood, you use a new version of pango with function pango_attr_insert_hyphens_new.

Underlining/overstriking support?

Please add support of underlining and overstriking a la ul(1) expressed with backspace characters.
Allowing arbitrary overstriking when a mono font is used would be a plus.

How to build?

From reading the INSTALL file, it seems it is out-of-date.
Are there instructions for building this project using make, etc?

The INSTALL docs talk about running ./configure, but that file does not exist.

I do see the autogen.sh script, but running that gives errors; for example:

$ ./autogen.sh --prefix=/home/user/.local
Copying file po/Makefile.in.in

Please add the files
  codeset.m4 gettext.m4 glibc21.m4 iconv.m4 isc-posix.m4 lcmessage.m4
  progtest.m4
from the /usr/share/aclocal directory to your autoconf macro directory
or directly to your aclocal.m4 file.
You will also need config.guess and config.sub, which you can get from
ftp://ftp.gnu.org/pub/gnu/config/.

./autogen.sh: 5: ./autogen.sh: intltoolize: not found
configure.ac:19: error: possibly undefined macro: AC_PROG_INTLTOOL
      If this token and others are legitimate, please use m4_pattern_allow.
      See the Autoconf documentation.
autoreconf: /usr/bin/autoconf failed with exit status: 1
configure: error: cannot find install-sh, install.sh, or shtool in config "."/config

I imagine I need to install some set of autoconf-related dependencies?

I also see the meson.build file; is that the main supported way of building, these days?

Unsupported mime type application/octet-stream when importing PDF to other application

The PDF documents produced by the latest paps seem to lack some metadata, including MIME type. This isn't a problem for opening and reading them on my host (Ubuntu 20.04). However, when I feed them to paperless-ngx, it refuses to ingest them, complaining about unsupported mime type.

paul@pauldev:~/Downloads$ paps -v
Version: paps-0.7.9

Generate test document:

paps --header --header-left="{filename}" --header-center="" --header-right="Page {page_idx:01d}/{num_pages:01d}" --footer --footer-left="Modified {mtime:%Y-%m-%d %H:%M}"--footer-right="Printed {now:%Y-%m-%d %H:%M}" --paper=letter --separation-lines --bottom-margin=42 --font="Roboto 10" --format=pdf 'test.txt' > test.pdf

Paperless server log when importing the PDF:

[2023-02-10 13:47:52,082] [INFO] [paperless.consumer] Consuming test.pdf
[2023-02-10 13:47:52,151] [ERROR] [paperless.consumer] Unsupported mime type application/octet-stream
[2023-02-10 13:47:52,180] [ERROR] [celery.app.trace] Task documents.tasks.consume_file[1f49b3f0-ea90-4fd5-bfbb-072e993ad954] raised unexpected: ConsumerError('test.pdf: Unsupported mime type application/octet-stream')

Exif tool shows metadata missing mime type:

paul@pauldev:~/Downloads$ exiftool test.pdf
ExifTool Version Number         : 11.88
File Name                       : test.pdf
Directory                       : .
File Size                       : 9.9 kB
File Modification Date/Time     : 2023:02:10 08:46:44-05:00
File Access Date/Time           : 2023:02:10 08:47:45-05:00
File Inode Change Date/Time     : 2023:02:10 08:46:44-05:00
File Permissions                : rw-rw-r--
Error                           : File format error

My workaround: Correct the PDF by piping/rewriting paps PDF through ghostscript:

paps --header --header-left="{filename}" --header-center="" --header-right="Page {page_idx:01d}/{num_pages:01d}" --footer --footer-left="Modified {mtime:%Y-%m-%d %H:%M}"--footer-right="Printed {now:%Y-%m-%d %H:%M}" --paper=letter --separation-lines --bottom-margin=42 --font="Roboto 10" --format=pdf test.txt - | gs -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE="test.pdf" -dBATCH -
GPL Ghostscript 9.50 (2019-10-15)
Copyright (C) 2019 Artifex Software, Inc.  All rights reserved.
This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY:
see the file COPYING for details.
   **** Warning: File has some garbage before %PDF- .
Processing pages 1 through 1.
Page 1

Exif tool after rewriting:

paul@pauldev:~/Downloads$ exiftool test.pdf
ExifTool Version Number         : 11.88
File Name                       : test.pdf
Directory                       : .
File Size                       : 11 kB
File Modification Date/Time     : 2023:02:10 08:54:21-05:00
File Access Date/Time           : 2023:02:10 08:54:24-05:00
File Inode Change Date/Time     : 2023:02:10 08:54:21-05:00
File Permissions                : rw-rw-r--
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
PDF Version                     : 1.7
Linearized                      : No
Page Count                      : 1
XMP Toolkit                     : XMP toolkit 2.9.1-13, framework 1.6
About                           : uuid:f7758c34-e166-11f8-0000-0bc720dc2f76
Producer                        : GPL Ghostscript 9.50
Modify Date                     : 2023:02:10 08:54:20-05:00
Create Date                     : 2023:02:10 08:54:20-05:00
Creator Tool                    : UnknownApplication
Document ID                     : uuid:f7758c34-e166-11f8-0000-0bc720dc2f76
Format                          : application/pdf
Title                           : Untitled

Paps is a great tool, and worth the effort to compile. I struggled to convert non-markdown text files to PDF using Pandoc. Paps is several times faster and supplies simple parameters to set the options I want. I hope you can add metadata entries to satisfy apps like paperless.

texttopaps (soft link to the paps) fails when invoking by cupsfilter

Hi,
I print text file on fedora31. The cups invokes "texttopaps" as a filter to convert file from text to postscript. And the printing successes.

But when I use "cupsfilter" command to invoke the "texttopaps", it always fails.
$cupsfilter -m application/postscript -d [printername] text.txt

INFO: texttopaps (PID 124239) started.
Failed to open 1!
ERROR: texttopaps (PID 124239) stopped with status 1

It seems texttopaps uses the [job-id] as [file], so it fails to open the [file].

I download the source and build the debug paps, as a result, the normal printing fails too.
Fails reason: texttopaps (soft link to the paps) use the job-id (when I debug, the job-id is 70) as [text file], it fails to open the file. The fails reason is same as the cupsfilter.

I investigated it, but has no clear result.
The texttopaps is softlink file to paps.
As a filter, the texttopaps accepts parameters: texttopaps job-id user title copies options [file]
But as a program, the paps accepts parameters: paps [OPTION…] [text file]
How does paps accept various parameters?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.