1
0
mirror of https://github.com/pdewacht/brlaser synced 2025-07-20 07:39:47 +02:00

44 Commits
v2 ... v4

Author SHA1 Message Date
d80491b105 Version 4 2018-02-25 18:47:30 +01:00
a521498233 Merge pull request #19 from StijnDW/master
Allow the user to define cups config variables
2018-02-17 19:04:27 +01:00
bd7a6f3179 Allow the user to define cups config variables
This is needed when the paths reported by cups-config are read-only.
As is the case in the NixOS distribution.
2018-02-17 18:52:46 +01:00
ba25b63af6 Add Brother DCP-7040 2018-01-29 08:06:48 +01:00
3946f2e3d6 Add Brother HL-L2300D 2018-01-28 22:34:10 +01:00
0536c6bcad Updated/expanded readme 2018-01-27 00:19:00 +01:00
3008302bb5 Add OpenBSD pledge 2018-01-27 00:18:19 +01:00
39ed3c5708 Cleanups 2018-01-27 00:18:19 +01:00
4209526ef0 setlocale shouldn't be needed 2018-01-27 00:18:19 +01:00
8007996fe7 Fix ppdc warning 2018-01-27 00:18:19 +01:00
cf4fbc86ba CMake: enable assert() for all build types 2018-01-27 00:18:19 +01:00
ab59a83caa Fix brlaser.drv for cmake conversion 2018-01-27 00:18:19 +01:00
6e9793833f CMake conversion 2018-01-27 00:18:19 +01:00
d25ba26132 Merge pull request #17 from blob79/install_ubuntu
Add documentation how to install under Ubuntu
2018-01-25 14:45:46 +01:00
fbcc6924e8 Add documentation how to install under Ubuntu 2017-12-09 08:04:29 +01:00
f1e0b2df54 Reduce log level of cupsRasterOpen failure
If cupsRasterOpen fails, the most likely cause is that some earlier
filter didn't produce any output. If we output an error-level message
in this situation, we'll likely displace some earlier, more useful
message by the other filter.
2017-11-02 00:06:58 +01:00
718053fa36 Add package name to all log messages 2017-10-30 20:07:27 +01:00
931c677443 Get rid of iconv()
PJL has a job name field. I don't think this is used for anything, but
just in case I want to put something human-readable there. But it's
also probably a good idea to keep this pure ASCII text.

Previously I used iconv() to convert the CUPS job name to ASCII. But:
- on FreeBSD, an explicit "-liconv" seems to be necessary (#10),
- there's an autoconf macro to deal with this, but it's tangled up
  with gettext and it seems like a hassle,
- the //TRANSLIT//IGNORE feature I used seems to be a GNU extension
  and probably won't work on other systems anyway.

So instead, let's just concatenate some job information together,
dropping any non-ASCII component. That's probably good enough.
2017-10-23 22:09:29 +02:00
853db9e5a2 Add Brother MFC-7360N
From Debian bug report #862750; thanks to Mark A. Hershberger.
2017-10-14 21:55:30 +02:00
2fd541c046 Clean up brlaser.drv.in 2017-10-14 21:53:45 +02:00
69cc0bfcc7 Merge remote-tracking branch 'xc-racer99/master' 2017-10-14 21:40:58 +02:00
4fdd8c95a8 Merge pull request #7 from rkreis/dcp1510
Add Brother-DCP1510
2017-10-14 20:57:58 +02:00
5d29d862c7 Merge pull request #5 from lnussel/master
mark DCP-7055W as supported
2017-10-14 20:57:34 +02:00
c58a3b8edd Merge pull request #12 from hollobon/patch-1
Fix typo
2017-10-14 20:52:31 +02:00
c656586451 Merge pull request #9 from cinemast/patch-2
Add missing #include <string>
2017-10-14 20:52:02 +02:00
2859a8a7df Fix typo 2017-08-09 10:32:45 +01:00
f8021024c4 DCP-7065DN: Don't advertise 300DPI printing
The DCP-7065DN only supports 600 and 1200 DPI
2017-05-01 12:26:23 -07:00
7e59e6147e Add duplex code for DCP-7065DN
The official Brother driver treats Tumble and NoTumble differently, adding &l2S and &l1S respectively to the header.

Unfortunately, for me this resulted in missing lines in NoTumble.  By treating everything as Tumble and simply sending data rotated 180 for Tumble we get a good quality printout.
2017-05-01 12:26:22 -07:00
5c5118edc1 Move num_copies to only the header
It's not needed to be at the beginning of every page and messes up duplex printing if it is
2017-05-01 12:26:17 -07:00
9ccc56e1bc mark DCP-7055W as supported 2016-06-17 10:37:08 +02:00
93138fec87 Add missing #include <string> 2016-04-25 15:02:37 +02:00
d5aa1a55dd Add Brother-DCP1510 2016-03-26 13:24:59 +01:00
03bb366e75 Refuse to build without a C++11 compiler
We had a buggy version of the AX_CXX_COMPILE_STDCXX macro: it didn't
abort the build if no suitable compiler was found. Upgrade to the
current version.

Relevant on OpenBSD, where the default compiler does not support C++11.
2016-03-02 20:34:50 +01:00
d85b875627 Use cups-config --ldflags
This fixes link problems on NixOS.
2016-03-02 19:41:44 +01:00
569e3f7766 Reject unexpected raster formats 2015-01-31 23:16:35 +01:00
1474716b27 Misc cleanups, mostly in the test code 2015-01-31 23:13:48 +01:00
4f1a00d46a Rever the readme rename: breaks formatting on Github
This reverts commit 49bfc1be98.
2014-11-25 00:17:11 +01:00
49bfc1be98 Rename README.md to README 2014-11-25 00:10:23 +01:00
8b99cced73 Add Brother DCP-7055
Looks like this printer has some configuration options beyond what
brlaser currently knows about. But this offers basic functionality.
2014-11-25 00:04:14 +01:00
1dcd5b445e Fix lest.hpp dependency for the tests. 2014-07-07 13:05:01 +02:00
19edb1767b Kill a harmless dead store
Just because clang's scan-build complained about it.
2014-07-07 13:03:57 +02:00
c3999acbec Version 3 2014-07-07 12:55:16 +02:00
9c4336a8df Updated README 2014-06-30 22:21:22 +02:00
71bb29a3ca Add Brother DCP-7065DN 2014-06-30 22:19:49 +02:00
22 changed files with 410 additions and 720 deletions

27
.gitignore vendored
View File

@ -1,26 +1 @@
#
# Autotools
#
/Makefile
/Makefile.in
/aclocal.m4
/autom4te.cache
/build-aux
/config.*
/configure
/stamp-*
.deps/
.dirstamp
*.log
*.trs
#
# Binaries
#
/src/rastertobrlaser
/src/brdecode
/test/test_lest
/test/test_line
/test/test_block
/brlaser.drv
*.o
build/

137
CMakeLists.txt Normal file
View File

@ -0,0 +1,137 @@
cmake_minimum_required(VERSION 3.1)
project(brlaser CXX)
set(BRLASER_VERSION "4")
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "No build type selected, default to RelWithDebInfo")
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Build type (default RelWithDebInfo)" FORCE)
endif()
include(CMakePushCheckState)
include(CheckCXXCompilerFlag)
include(CheckIncludeFileCXX)
## Enable assertions for all builds
## (cmake by default sets NDEBUG for release builds)
foreach(var
CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_RELWITHDEBINFO
CMAKE_CXX_FLAGS_MINSIZEREL)
string(REGEX REPLACE "(^| )[/-]D *NDEBUG($| )" " " "${var}" "${${var}}")
endforeach()
## Configure the compiler
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
macro(extra_cxx_compiler_flag FLAG)
string(REGEX REPLACE "[^A-Za-z_0-9]" "_" SFLAG ${FLAG})
check_cxx_compiler_flag(${FLAG} COMPILER_SUPPORT_${SFLAG})
if(COMPILER_SUPPORT_${SFLAG})
set(EXTRA_CXX_FLAGS "${EXTRA_CXX_FLAGS} ${FLAG}")
endif()
endmacro(extra_cxx_compiler_flag)
# Compiler warnings
extra_cxx_compiler_flag("-Wall")
extra_cxx_compiler_flag("-Wno-missing-braces")
# Some security flags
extra_cxx_compiler_flag("-fstack-protector-strong")
extra_cxx_compiler_flag("-Wformat")
extra_cxx_compiler_flag("-Werror=format-security")
extra_cxx_compiler_flag("-D_FORTIFY_SOURCE=2")
# Enable the supported flags, but give priority to CXXFLAGS env var
set(CMAKE_CXX_FLAGS "${EXTRA_CXX_FLAGS} ${CMAKE_CXX_FLAGS}")
## Configure CUPS
find_program(CUPS_CONFIG NAMES cups-config)
if(NOT CUPS_CONFIG)
message(FATAL_ERROR "cups-config command not found. Are the CUPS development packages installed?")
endif()
if(NOT CUPS_DATA_DIR)
execute_process(
COMMAND "${CUPS_CONFIG}" --datadir
OUTPUT_VARIABLE CUPS_DATA_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
if(NOT CUPS_SERVER_BIN)
execute_process(
COMMAND "${CUPS_CONFIG}" --serverbin
OUTPUT_VARIABLE CUPS_SERVER_BIN
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
if(NOT CUPS_CFLAGS)
execute_process(
COMMAND "${CUPS_CONFIG}" --cflags
OUTPUT_VARIABLE CUPS_CFLAGS
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
if(NOT CUPS_LDFLAGS)
execute_process(
COMMAND "${CUPS_CONFIG}" --ldflags
OUTPUT_VARIABLE CUPS_LDFLAGS
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
if(NOT CUPS_LIBS)
execute_process(
COMMAND "${CUPS_CONFIG}" --image --libs
OUTPUT_VARIABLE CUPS_LIBS
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
cmake_push_check_state()
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${CUPS_CFLAGS}")
check_include_file_cxx(cups/raster.h HAVE_CUPS_RASTER_H)
cmake_pop_check_state()
if(NOT HAVE_CUPS_RASTER_H)
message(SEND_ERROR "<cups/raster.h> header not found. Are the CUPS development packages installed?")
endif()
## Build instructions
configure_file(
"${PROJECT_SOURCE_DIR}/brlaser.drv.in"
"${PROJECT_BINARY_DIR}/brlaser.drv")
configure_file(
"${PROJECT_SOURCE_DIR}/config.h.in"
"${PROJECT_BINARY_DIR}/config.h")
include_directories("${PROJECT_BINARY_DIR}")
add_executable(rastertobrlaser src/main.cc src/job.cc src/line.cc src/debug.cc)
target_compile_options(rastertobrlaser PRIVATE ${CUPS_CFLAGS})
target_link_libraries(rastertobrlaser ${CUPS_LIBS})
target_link_libraries(rastertobrlaser ${CUPS_LDFLAGS})
add_executable(brdecode src/brdecode.cc)
add_executable(test_lest test/test_lest.cc)
add_executable(test_line test/test_line.cc src/line.cc)
add_executable(test_block test/test_block.cc)
enable_testing()
add_test(test_lest test_lest)
add_test(test_line test_line)
add_test(test_block test_block)
# Autotools-style "make check" command
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
add_dependencies(check test_lest test_line test_block)
# Installation
install(
TARGETS rastertobrlaser
DESTINATION "${CUPS_SERVER_BIN}/filter")
install(
FILES "${PROJECT_BINARY_DIR}/brlaser.drv"
DESTINATION "${CUPS_DATA_DIR}/drv")

View File

@ -1,3 +1,11 @@
brlaser v4 (2018-02-25)
Added several printers.
Merged duplex printing support from @xc-racer99. Enabled for DCP-7065DN.
Switched to a CMake build system.
brlaser v3 (2014-07-07)
Added DCP-7065DN description.
brlaser v2 (2014-06-29)
Suppport compilation with GCC 4.6.
Add a basic test suite.

View File

@ -1,50 +0,0 @@
ACLOCAL_AMFLAGS = -I m4
AM_CXXFLAGS = $(CUPS_CFLAGS)
TESTS = $(check_PROGRAMS)
dist_doc_DATA = README.md
drv_DATA = brlaser.drv
drvdir = $(CUPS_DATADIR)/drv
filter_PROGRAMS = src/rastertobrlaser
filterdir = $(CUPS_SERVERBIN)/filter
noinst_PROGRAMS = src/brdecode
check_PROGRAMS = \
test/test_lest \
test/test_line \
test/test_block
src_rastertobrlaser_SOURCES = \
src/main.cc \
src/debug.h \
src/debug.cc \
src/job.h \
src/job.cc \
src/block.h \
src/line.h \
src/line.cc
src_rastertobrlaser_LDADD = $(CUPS_LIBS)
src_brdecode_SOURCES = \
src/brdecode.cc
test_test_lest_SOURCES = \
test/test_lest.cc \
test/lest.h
test_test_line_SOURCES = \
test/test_line.cc \
src/line.h \
src/line.cc \
test/lest.h
test_test_block_SOURCES = \
test/test_block.cc \
src/block.h \
test/tempfile.h \
test/lest.h

View File

@ -1,23 +1,70 @@
"brlaser" Brother DCP-7030 printer driver
=========================================
brlaser: Brother laser printer driver
=====================================
This is a driver for the Brother DCP-7030 laser printer. It might also
be worth trying if you have some other old Brother monochrome laser
printer.
brlaser is a CUPS driver for Brother laser printers.
Currently this printer is not supported by other free software
drivers. Ghostscript's hl1250 driver almost works, but has glitches
with some fonts. (That driver tries to use PCL emulation, but that
seems to be buggy on this printer. The proprietary driver never uses
that mode.)
Although most Brother printers support a standard printer language
such as PCL or PostScript, not all do. If you have a monochrome
Brother laser printer (or multi-function device) and the other open
source drivers don't work, this one might help.
Brother provides a non-free x86-only driver.
This driver is known to work with these printers:
Requirements
* Brother DCP-1510
* Brother DCP-7030
* Brother DCP-7040
* Brother DCP-7055
* Brother DCP-7055W
* Brother DCP-7065DN
* Brother HL-L2300D
* Brother MFC-7360N
Other printers
--------------
If your printer isn't included in the list above, just try selecting
any entry marked 'brlaser' and see if it works.
If it does, please create a new issue here in Github and include the
output of this command:
sudo lpinfo --include-schemes usb -l -v
Then I'll be able to add a proper entry for your printer.
Installation
------------
* CUPS: tested with version 1.6.
* A C++11 compiler: GCC 4.6 or later, or a recent version of Clang.
Some operating systems already ship this driver. This is the case for
at least Debian, Ubuntu, Raspbian, openSUSE, NixOS and Arch Linux.
Look for a package named `printer-driver-brlaser`.
You'll also need Ghostscript, in case that's not installed
automatically.
Once brlaser is installed, you can add your printer using the usual
CUPS interface.
Building from source
--------------------
To compile brlaser you'll need CMake and the CUPS development packages
(libcups2-dev, libcupsimage2-dev or similar).
Get the code by cloning the git repo <!-- or downloading the [latest
release] -->. Compile and install with these commands:
cmake .
make
sudo make install
It might be needed to restart CUPS after this.
[latest release]: https://github.com/pdewacht/brlaser/releases/latest
Copyright
---------

View File

@ -1,15 +0,0 @@
#! /bin/sh
srcdir=`dirname "$0"`
test -z "$srcdir" && srcdir=.
ORIGDIR=`pwd`
cd "$srcdir"
autoreconf --force -v --install || exit 1
cd "$ORIGDIR" || exit $?
if test -z "$NOCONFIGURE"; then
exec "$srcdir"/configure "$@"
fi

View File

@ -15,6 +15,8 @@
// You should have received a copy of the GNU General Public License
// along with brlaser. If not, see <http://www.gnu.org/licenses/>.
#define USING "using @CMAKE_PROJECT_NAME@ v@BRLASER_VERSION@"
// Include standard font and media definitions
#include <font.defs>
#include <media.defs>
@ -24,7 +26,7 @@ Font *
// Manufacturer and driver version.
Manufacturer "Brother"
Version @VERSION@
Version "@BRLASER_VERSION@"
// Each filter provided by the driver...
Filter application/vnd.cups-raster 33 rastertobrlaser
@ -33,7 +35,9 @@ Filter application/vnd.cups-raster 33 rastertobrlaser
// The 1200dpi mode is weird: we need to send 1200x1200dpi raster
// data, but Brother only advertises 1200x600dpi. I wonder what
// is going on there.
Resolution k 1 0 0 0 "300dpi/300 DPI"
// The 300dpi mode is reportedly not supported on all printers, so
// it's listed in individual printer blocks where we believe it works.
// Resolution k 1 0 0 0 "300dpi/300 DPI"
*Resolution k 1 0 0 0 "600dpi/600 DPI"
Resolution k 1 0 0 0 "1200dpi/1200HQ"
@ -46,7 +50,7 @@ MediaSize B5
MediaSize B6
MediaSize EnvC5
MediaSize EnvMonarch
MediaSize EnvPRC5
MediaSize EnvDL
MediaSize Executive
MediaSize Legal
MediaSize Letter
@ -75,9 +79,65 @@ Option "brlaserEconomode/Toner save mode" Boolean AnySetup 10
Choice True/On "<</cupsInteger10 1>>setpagedevice"
{
ModelName "DCP-1510"
Attribute "NickName" "" "Brother DCP-1510 series, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,XL2HB;MDL:DCP-1510 series;CLS:PRINTER;CID:Brother Laser Type1;"
Resolution k 1 0 0 0 "300dpi/300 DPI"
PCFileName "br1510.ppd"
}
{
ModelName "DCP-7030"
Attribute "NickName" "" "Brother DCP-7030, using @PACKAGE@ v@VERSION@"
Attribute "NickName" "" "Brother DCP-7030, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:DCP-7030;CLS:PRINTER;"
Resolution k 1 0 0 0 "300dpi/300 DPI"
PCFileName "br7030.ppd"
}
{
ModelName "DCP-7040"
Attribute "NickName" "" "Brother DCP-7040, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:DCP-7040;CLS:PRINTER;"
Resolution k 1 0 0 0 "300dpi/300 DPI"
PCFileName "br7040.ppd"
}
{
ModelName "DCP-7055"
Attribute "NickName" "" "Brother DCP-7055, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:DCP-7055;CLS:PRINTER;CID:Brother Laser Type1;"
Resolution k 1 0 0 0 "300dpi/300 DPI"
PCFileName "br7055.ppd"
}
{
ModelName "DCP-7055W"
Attribute "NickName" "" "Brother DCP-7055W, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:DCP-7055W;CLS:PRINTER;CID:Brother Laser Type1;"
Resolution k 1 0 0 0 "300dpi/300 DPI"
PCFileName "br7055w.ppd"
}
{
ModelName "DCP-7065DN"
Attribute "NickName" "" "Brother DCP-7065DN, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:DCP-7065DN;CLS:PRINTER;CID:Brother Laser Type1;"
Duplex rotated
PCFileName "br7065dn.ppd"
}
{
ModelName "HL-L2300D"
Attribute "NickName" "" "Brother HL-L2300D, $USING"
Attribute "1284DeviceID" "" " MFG:Brother;CMD:PJL,HBP;MDL:HL-L2300D series;CLS:PRINTER;CID:Brother Laser Type1;"
Duplex rotated
PCFileName "brl2300d.ppd"
}
{
ModelName "MFC-7360N"
Attribute "NickName" "" "Brother MFC-7360N, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:MFC-7360N;CLS:PRINTER;CID:Brother Laser Type1;"
PCFileName "br7360n.ppd"
}

2
config.h.in Normal file
View File

@ -0,0 +1,2 @@
#define PACKAGE "@CMAKE_PROJECT_NAME@"
#define VERSION "@BRLASER_VERSION@"

View File

@ -1,57 +0,0 @@
# This file is part of the brlaser printer driver.
#
# Copyright 2013 Peter De Wachter
#
# brlaser is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# brlaser is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with brlaser. If not, see <http:#www.gnu.org/licenses/>.
AC_PREREQ(2.68)
AC_INIT([brlaser], [2], [pdewacht@gmail.com], [brlaser],
[https://github.com/pdewacht/brlaser])
AC_CONFIG_SRCDIR([src/line.cc])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
AC_LANG([C++])
AM_INIT_AUTOMAKE([1.11.1 foreign subdir-objects dist-xz -Wall -Werror])
AM_MAINTAINER_MODE([enable])
AM_SILENT_RULES([yes])
AC_PROG_CXX
AX_CXX_COMPILE_STDCXX_11
AX_CXXFLAGS_WARN_ALL
dnl Use cups-config to detect the CUPS configuration.
AC_PATH_PROG(CUPS_CONFIG, cups-config)
AS_IF([test -z "$CUPS_CONFIG"],
[AC_MSG_ERROR(["cups-config" command not found. Please install the CUPS development package.])])
CUPS_CFLAGS=`"$CUPS_CONFIG" --cflags`
CUPS_LIBS=`"$CUPS_CONFIG" --image --libs`
CUPS_SERVERBIN=`"$CUPS_CONFIG" --serverbin`
CUPS_DATADIR=`"$CUPS_CONFIG" --datadir`
AC_SUBST(CUPS_CFLAGS)
AC_SUBST(CUPS_LIBS)
AC_SUBST(CUPS_SERVERBIN)
AC_SUBST(CUPS_DATADIR)
dnl 'cups-config --libs' lists a lot of libs we don't need/want,
dnl try to figure out whether the linker knows about --as-needed.
AC_ARG_ENABLE([as-needed],
AC_HELP_STRING([--disable-as-needed], [disable overlinking protection]))
AS_IF([test "x$enable_as_needed" != "xno"],
[AX_APPEND_LINK_FLAGS([-Wl,--as-needed])])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile brlaser.drv])
AC_OUTPUT

View File

@ -1,69 +0,0 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_append_flag.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE])
#
# DESCRIPTION
#
# FLAG is appended to the FLAGS-VARIABLE shell variable, with a space
# added in between.
#
# If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
# CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains
# FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly
# FLAG.
#
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION.
#
# LICENSE
#
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 2
AC_DEFUN([AX_APPEND_FLAG],
[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX
AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])dnl
AS_VAR_SET_IF(FLAGS,
[case " AS_VAR_GET(FLAGS) " in
*" $1 "*)
AC_RUN_LOG([: FLAGS already contains $1])
;;
*)
AC_RUN_LOG([: FLAGS="$FLAGS $1"])
AS_VAR_SET(FLAGS, ["AS_VAR_GET(FLAGS) $1"])
;;
esac],
[AS_VAR_SET(FLAGS,["$1"])])
AS_VAR_POPDEF([FLAGS])dnl
])dnl AX_APPEND_FLAG

View File

@ -1,61 +0,0 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_append_link_flags.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_APPEND_LINK_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS])
#
# DESCRIPTION
#
# For every FLAG1, FLAG2 it is checked whether the linker works with the
# flag. If it does, the flag is added FLAGS-VARIABLE
#
# If FLAGS-VARIABLE is not specified, the linker's flags (LDFLAGS) is
# used. During the check the flag is always added to the linker's flags.
#
# If EXTRA-FLAGS is defined, it is added to the linker's default flags
# when the check is done. The check is thus made with the flags: "LDFLAGS
# EXTRA-FLAGS FLAG". This can for example be used to force the linker to
# issue an error when a bad flag is given.
#
# NOTE: This macro depends on the AX_APPEND_FLAG and AX_CHECK_LINK_FLAG.
# Please keep this macro in sync with AX_APPEND_COMPILE_FLAGS.
#
# LICENSE
#
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 2
AC_DEFUN([AX_APPEND_LINK_FLAGS],
[for flag in $1; do
AX_CHECK_LINK_FLAG([$flag], [AX_APPEND_FLAG([$flag], [m4_default([$2], [LDFLAGS])])], [], [$3])
done
])dnl AX_APPEND_LINK_FLAGS

View File

@ -1,122 +0,0 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_cflags_warn_all.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_CFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])]
# AX_CXXFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])]
# AX_FCFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])]
#
# DESCRIPTION
#
# Try to find a compiler option that enables most reasonable warnings.
#
# For the GNU compiler it will be -Wall (and -ansi -pedantic) The result
# is added to the shellvar being CFLAGS, CXXFLAGS, or FCFLAGS by default.
#
# Currently this macro knows about the GCC, Solaris, Digital Unix, AIX,
# HP-UX, IRIX, NEC SX-5 (Super-UX 10), Cray J90 (Unicos 10.0.0.8), and
# Intel compilers. For a given compiler, the Fortran flags are much more
# experimental than their C equivalents.
#
# - $1 shell-variable-to-add-to : CFLAGS, CXXFLAGS, or FCFLAGS
# - $2 add-value-if-not-found : nothing
# - $3 action-if-found : add value to shellvariable
# - $4 action-if-not-found : nothing
#
# NOTE: These macros depend on AX_APPEND_FLAG.
#
# LICENSE
#
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
# Copyright (c) 2010 Rhys Ulerich <rhys.ulerich@gmail.com>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 14
AC_DEFUN([AX_FLAGS_WARN_ALL],[dnl
AS_VAR_PUSHDEF([FLAGS],[_AC_LANG_PREFIX[]FLAGS])dnl
AS_VAR_PUSHDEF([VAR],[ac_cv_[]_AC_LANG_ABBREV[]flags_warn_all])dnl
AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for maximum warnings],
VAR,[VAR="no, unknown"
ac_save_[]FLAGS="$[]FLAGS"
for ac_arg dnl
in "-warn all % -warn all" dnl Intel
"-pedantic % -Wall" dnl GCC
"-xstrconst % -v" dnl Solaris C
"-std1 % -verbose -w0 -warnprotos" dnl Digital Unix
"-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" dnl AIX
"-ansi -ansiE % -fullwarn" dnl IRIX
"+ESlit % +w1" dnl HP-UX C
"-Xc % -pvctl[,]fullmsg" dnl NEC SX-5 (Super-UX 10)
"-h conform % -h msglevel 2" dnl Cray C (Unicos)
#
do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
[VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
done
FLAGS="$ac_save_[]FLAGS"
])
AS_VAR_POPDEF([FLAGS])dnl
AC_REQUIRE([AX_APPEND_FLAG])
case ".$VAR" in
.ok|.ok,*) m4_ifvaln($3,$3) ;;
.|.no|.no,*) m4_default($4,[m4_ifval($2,[AX_APPEND_FLAG([$2], [$1])])]) ;;
*) m4_default($3,[AX_APPEND_FLAG([$VAR], [$1])]) ;;
esac
AS_VAR_POPDEF([VAR])dnl
])dnl AX_FLAGS_WARN_ALL
dnl implementation tactics:
dnl the for-argument contains a list of options. The first part of
dnl these does only exist to detect the compiler - usually it is
dnl a global option to enable -ansi or -extrawarnings. All other
dnl compilers will fail about it. That was needed since a lot of
dnl compilers will give false positives for some option-syntax
dnl like -Woption or -Xoption as they think of it is a pass-through
dnl to later compile stages or something. The "%" is used as a
dnl delimiter. A non-option comment can be given after "%%" marks
dnl which will be shown but not added to the respective C/CXXFLAGS.
AC_DEFUN([AX_CFLAGS_WARN_ALL],[dnl
AC_LANG_PUSH([C])
AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4])
AC_LANG_POP([C])
])
AC_DEFUN([AX_CXXFLAGS_WARN_ALL],[dnl
AC_LANG_PUSH([C++])
AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4])
AC_LANG_POP([C++])
])
AC_DEFUN([AX_FCFLAGS_WARN_ALL],[dnl
AC_LANG_PUSH([Fortran])
AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4])
AC_LANG_POP([Fortran])
])

View File

@ -1,73 +0,0 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
#
# DESCRIPTION
#
# Check whether the given FLAG works with the linker or gives an error.
# (Warnings, however, are ignored)
#
# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
# success/failure.
#
# If EXTRA-FLAGS is defined, it is added to the linker's default flags
# when the check is done. The check is thus made with the flags: "LDFLAGS
# EXTRA-FLAGS FLAG". This can for example be used to force the linker to
# issue an error when a bad flag is given.
#
# INPUT gives an alternative input source to AC_LINK_IFELSE.
#
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG.
#
# LICENSE
#
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 3
AC_DEFUN([AX_CHECK_LINK_FLAG],
[AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl
AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [
ax_check_save_flags=$LDFLAGS
LDFLAGS="$LDFLAGS $4 $1"
AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
[AS_VAR_SET(CACHEVAR,[yes])],
[AS_VAR_SET(CACHEVAR,[no])])
LDFLAGS=$ax_check_save_flags])
AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes],
[m4_default([$2], :)],
[m4_default([$3], :)])
AS_VAR_POPDEF([CACHEVAR])dnl
])dnl AX_CHECK_LINK_FLAGS

View File

@ -1,133 +0,0 @@
# ============================================================================
# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html
# ============================================================================
#
# SYNOPSIS
#
# AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional])
#
# DESCRIPTION
#
# Check for baseline language coverage in the compiler for the C++11
# standard; if necessary, add switches to CXXFLAGS to enable support.
#
# The first argument, if specified, indicates whether you insist on an
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
# -std=c++11). If neither is specified, you get whatever works, with
# preference for an extended mode.
#
# The second argument, if specified 'mandatory' or if left unspecified,
# indicates that baseline C++11 support is required and that the macro
# should error out if no mode with that support is found. If specified
# 'optional', then configuration proceeds regardless, after defining
# HAVE_CXX11 if and only if a supporting mode is found.
#
# LICENSE
#
# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 3
m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [
template <typename T>
struct check
{
static_assert(sizeof(int) <= sizeof(T), "not big enough");
};
typedef check<check<bool>> right_angle_brackets;
int a;
decltype(a) b;
typedef check<int> check_type;
check_type c;
check_type&& cr = static_cast<check_type&&>(c);
auto d = a;
])
AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl
m4_if([$1], [], [],
[$1], [ext], [],
[$1], [noext], [],
[m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl
m4_if([$2], [], [ax_cxx_compile_cxx11_required=true],
[$2], [mandatory], [ax_cxx_compile_cxx11_required=true],
[$2], [optional], [ax_cxx_compile_cxx11_required=false],
[m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])])dnl
AC_LANG_PUSH([C++])dnl
ac_success=no
AC_CACHE_CHECK(whether $CXX supports C++11 features by default,
ax_cv_cxx_compile_cxx11,
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
[ax_cv_cxx_compile_cxx11=yes],
[ax_cv_cxx_compile_cxx11=no])])
if test x$ax_cv_cxx_compile_cxx11 = xyes; then
ac_success=yes
fi
m4_if([$1], [noext], [], [dnl
if test x$ac_success = xno; then
for switch in -std=gnu++11 -std=gnu++0x; do
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
$cachevar,
[ac_save_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS $switch"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
[eval $cachevar=yes],
[eval $cachevar=no])
CXXFLAGS="$ac_save_CXXFLAGS"])
if eval test x\$$cachevar = xyes; then
CXXFLAGS="$CXXFLAGS $switch"
ac_success=yes
break
fi
done
fi])
m4_if([$1], [ext], [], [dnl
if test x$ac_success = xno; then
for switch in -std=c++11 -std=c++0x; do
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
$cachevar,
[ac_save_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS $switch"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
[eval $cachevar=yes],
[eval $cachevar=no])
CXXFLAGS="$ac_save_CXXFLAGS"])
if eval test x\$$cachevar = xyes; then
CXXFLAGS="$CXXFLAGS $switch"
ac_success=yes
break
fi
done
fi])
AC_LANG_POP([C++])
if test x$ax_cxx_compile_cxx11_required = xtrue; then
if test x$ac_success = xno; then
AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.])
fi
else
if test x$ac_success = xno; then
HAVE_CXX11=0
AC_MSG_NOTICE([No compiler with C++11 support was found])
else
HAVE_CXX11=1
AC_DEFINE(HAVE_CXX11,1,
[define if the compiler supports basic C++11 syntax])
fi
AC_SUBST(HAVE_CXX11)
fi
])

View File

@ -25,13 +25,18 @@
class block {
public:
block(): line_bytes_(0) {
lines_.reserve(max_lines_per_block_);
}
bool empty() const {
return line_bytes_ == 0;
}
void add_line(std::vector<uint8_t> &&line) {
assert(!line.empty());
assert(line_fits(line.size()));
line_bytes_ += line.size();
lines_.push_back(line);
lines_.emplace_back(line);
}
bool line_fits(unsigned size) {
@ -40,7 +45,7 @@ class block {
}
void flush(FILE *f) {
if (line_bytes_) {
if (!empty()) {
fprintf(f, "%dw%c%c",
line_bytes_ + 2, 0,
static_cast<int>(lines_.size()));

View File

@ -21,6 +21,7 @@
#include <algorithm>
#include <exception>
#include <vector>
#include <string>
namespace {
@ -143,7 +144,6 @@ bool read_page() {
line.clear();
while ((ch = getc(in_file)) >= 0) {
if (ch == '\f') {
in_esc = false;
break;
} else if (ch == 033) {
in_esc = true;

View File

@ -15,6 +15,7 @@
// You should have received a copy of the GNU General Public License
// along with brlaser. If not, see <http://www.gnu.org/licenses/>.
#include "config.h"
#include "debug.h"
#include <iostream>
#include <typeinfo>
@ -23,12 +24,12 @@ namespace {
template <typename T>
void dump(const char *name, const T &value) {
std::cerr << "DEBUG: page header: " << name << " = " << value << '\n';
std::cerr << "DEBUG: " PACKAGE ": page header: " << name << " = " << value << '\n';
}
template <typename T, int N>
void dump(const char *name, const T (&value)[N]) {
std::cerr << "DEBUG: page header: " << name << " =";
std::cerr << "DEBUG: " PACKAGE ": page header: " << name << " =";
for (int i = 0; i < N; ++i) {
std::cerr << ' ' << value[i];
}
@ -36,12 +37,12 @@ void dump(const char *name, const T (&value)[N]) {
}
void dump(const char *name, const char *value) {
std::cerr << "DEBUG: page header: " << name << " = \"" << value << "\"\n";
std::cerr << "DEBUG: " PACKAGE ": page header: " << name << " = \"" << value << "\"\n";
}
template <int N, int M>
void dump(const char *name, const char (&value)[N][M]) {
std::cerr << "DEBUG: page header: " << name << " =";
std::cerr << "DEBUG: " PACKAGE ": page header: " << name << " =";
for (int i = 0; i < N; ++i) {
std::cerr << " \"" << value[i] << '"';
}

View File

@ -73,10 +73,16 @@ void job::write_page_header() {
fprintf(out_, "@PJL SET PAGEPROTECT = AUTO\n");
fprintf(out_, "@PJL SET ORIENTATION = PORTRAIT\n");
fprintf(out_, "@PJL ENTER LANGUAGE = PCL\n");
fputs("\033E", out_);
fprintf(out_, "\033&l%dX", std::max(1, page_params_.num_copies));
if (page_params_.duplex) {
fputs("\033&l2S", out_);
}
}
void job::encode_page(const page_params &page_params,
int num_copies,
int lines,
int linesize,
nextline_fn nextline) {
@ -89,17 +95,15 @@ void job::encode_page(const page_params &page_params,
std::vector<uint8_t> reference(linesize);
block block;
if (!nextline(line.data())) {
if (!nextline(line)) {
return;
}
block.add_line(encode_line(line));
std::swap(line, reference);
fputs("\033E", out_);
fprintf(out_, "\033&l%dX", std::max(1, num_copies));
fputs("\033*b1030m", out_);
for (int i = 1; i < lines && nextline(line.data()); ++i) {
for (int i = 1; i < lines && nextline(line); ++i) {
std::vector<uint8_t> encoded = encode_line(line, reference);
if (!block.line_fits(encoded.size())) {
block.flush(out_);

View File

@ -21,16 +21,21 @@
#include <stdint.h>
#include <stdio.h>
#include <string>
#include <vector>
struct page_params {
int num_copies;
int resolution;
bool duplex;
bool economode;
std::string sourcetray;
std::string mediatype;
std::string papersize;
bool operator==(const page_params &o) const {
return resolution == o.resolution
return num_copies == o.num_copies
&& resolution == o.resolution
&& duplex == o.duplex
&& economode == o.economode
&& sourcetray == o.sourcetray
&& mediatype == o.mediatype
@ -40,13 +45,12 @@ struct page_params {
class job {
public:
typedef bool (*nextline_fn)(uint8_t *buf);
typedef bool (*nextline_fn)(std::vector<uint8_t> &buf);
explicit job(FILE *out, const std::string &job_name);
~job();
void encode_page(const page_params &params,
int num_copies,
int lines,
int linesize,
nextline_fn nextline);

View File

@ -17,8 +17,6 @@
#include <stdio.h>
#include <signal.h>
#include <locale.h>
#include <iconv.h>
#include <unistd.h>
#include <fcntl.h>
#include <cups/raster.h>
@ -31,64 +29,60 @@
#include "job.h"
#include "debug.h"
namespace {
cups_raster_t *ras;
volatile sig_atomic_t interrupted = 0;
void sigterm_handler(int sig) {
interrupted = 1;
}
cups_raster_t *ras;
cups_page_header2_t header;
bool next_line(uint8_t *buf) {
bool next_line(std::vector<uint8_t> &buf) {
if (interrupted) {
return false;
}
unsigned bytes = header.cupsBytesPerLine;
return cupsRasterReadPixels(ras, buf, bytes) == bytes;
return cupsRasterReadPixels(ras, buf.data(), buf.size()) == buf.size();
}
// POSIX says the second argument of iconv has type 'char **', but
// some systems have 'const char **'. This class is used to work
// around this incompatibility.
class sloppy_ptr {
public:
explicit sloppy_ptr(const char **ptr): ptr_(ptr) { }
operator const char **() { return ptr_; }
operator char **() { return const_cast<char **>(ptr_); }
private:
const char **ptr_;
};
std::string ascii_job_name(const char *job_name, const char *charset) {
if (job_name && charset) {
iconv_t cd = iconv_open("ASCII//TRANSLIT//IGNORE", charset);
if (cd != (iconv_t) -1) {
char ascii[80];
const char *in_ptr = job_name;
size_t in_left = strlen(job_name);
char *out_ptr = ascii;
size_t out_left = sizeof(ascii) - 1;
while (in_left > 0) {
size_t err = iconv(cd,
sloppy_ptr(&in_ptr), &in_left,
&out_ptr, &out_left);
if (err == (size_t) -1) {
break;
}
bool plain_ascii_string(const char *str) {
bool result = true;
for (; result && *str; str++) {
result = *str >= 32 && *str <= 126;
}
return result;
}
std::string ascii_job_name(const char *job_id, const char *job_user, const char *job_name) {
std::array<const char *, 3> parts = {{
job_id,
job_user,
job_name
}};
std::string result;
for (const char *part : parts) {
if (*part && plain_ascii_string(part)) {
if (!result.empty()) {
result += '/';
}
*out_ptr = 0;
iconv_close(cd);
return ascii;
result += part;
}
}
return "CUPS";
if (result.empty()) {
result = "brlaser";
}
const int max_size = 79;
if (result.size() > max_size) {
result.resize(max_size);
}
return result;
}
page_params build_page_params() {
page_params build_page_params(const cups_page_header2_t &header) {
static const std::array<std::string, 6> sources = {{
"AUTO", "T1", "T2", "T3", "MP", "MANUAL"
}};
@ -101,15 +95,18 @@ page_params build_page_params() {
{ "EnvC5", "C5" },
{ "EnvMonarch", "MONARCH" },
{ "EnvPRC5", "DL" },
{ "EnvDL", "DL" },
{ "Executive", "EXECUTIVE" },
{ "Legal", "LEGAL" },
{ "Letter", "LETTER" }
};
page_params p = { };
p.num_copies = header.NumCopies;
p.resolution = header.HWResolution[0];
p.economode = header.cupsInteger[10];
p.mediatype = header.MediaType;
p.duplex = header.Duplex;
if (header.MediaPosition < sources.size())
p.sourcetray = sources[header.MediaPosition];
@ -128,66 +125,80 @@ page_params build_page_params() {
} // namespace
int main(int argc, char *argv[]) {
fprintf(stderr, "INFO: %s version %s\n", PACKAGE, VERSION);
if (argc != 6 && argc != 7) {
fprintf(stderr, "ERROR: %s job-id user title copies options [file]\n", argv[0]);
fprintf(stderr, "ERROR: rastertobrlaser job-id user title copies options [file]\n");
fprintf(stderr, "INFO: This program is a CUPS filter. It is not intended to be run manually.\n");
return 1;
}
// const char *job_id = argv[1];
// const char *job_user = argv[2];
const char *job_id = argv[1];
const char *job_user = argv[2];
const char *job_name = argv[3];
// const int job_copies = atoi(argv[4]);
// const char *job_options = argv[5];
const char *job_filename = argv[6];
const char *job_charset = getenv("CHARSET");
setlocale(LC_ALL, "");
// const char *job_charset = getenv("CHARSET");
signal(SIGTERM, sigterm_handler);
signal(SIGPIPE, SIG_IGN);
int fd = 0;
int fd = STDIN_FILENO;
if (job_filename) {
fd = open(job_filename, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "ERROR: Unable to open raster file\n");
fprintf(stderr, "ERROR: " PACKAGE ": Unable to open raster file\n");
return 1;
}
}
#ifdef __OpenBSD__
if (pledge("stdio", nullptr) != 0) {
fprintf(stderr, "ERROR: " PACKAGE ": pledge failed\n");
return 1;
}
#endif
ras = cupsRasterOpen(fd, CUPS_RASTER_READ);
if (!ras) {
fprintf(stderr, "ERROR: Can't read raster data\n");
fprintf(stderr, "DEBUG: " PACKAGE ": Cannot read raster data. Most likely an earlier filter in the pipeline failed.\n");
return 1;
}
int pages = 0;
{
job job(stdout, ascii_job_name(job_name, job_charset));
job job(stdout, ascii_job_name(job_id, job_user, job_name));
cups_page_header2_t header;
while (!interrupted && cupsRasterReadHeader2(ras, &header)) {
if (header.cupsBitsPerPixel != 1
|| header.cupsBitsPerColor != 1
|| header.cupsNumColors != 1
|| header.cupsBytesPerLine > 10000) {
fprintf(stderr, "ERROR: " PACKAGE ": Page %d: Bogus raster data.\n", pages + 1);
dump_page_header(header);
return 1;
}
if (pages == 0) {
fprintf(stderr, "DEBUG: " PACKAGE ": Page header of first page\n");
dump_page_header(header);
}
job.encode_page(build_page_params(),
header.NumCopies,
job.encode_page(build_page_params(header),
header.cupsHeight,
header.cupsBytesPerLine,
next_line);
fprintf(stderr, "PAGE: %d %d\n", ++pages, header.NumCopies);
}
}
if (pages == 0) {
fprintf(stderr, "ERROR: No pages were found.");
fprintf(stderr, "ERROR: " PACKAGE ": No pages were found.\n");
return 1;
}
fflush(stdout);
if (ferror(stdout)) {
fprintf(stderr, "ERROR: Could not write print data\n");
fprintf(stderr, "DEBUG: " PACKAGE ": Could not write print data. Most likely the CUPS backend failed.\n");
return 1;
}
return 0;

View File

@ -19,12 +19,25 @@
#include <stdint.h>
#include <vector>
#include "tempfile.h"
#include "src/block.h"
#include "../src/block.h"
typedef std::vector<uint8_t> vec;
const lest::test specification[] = {
"Block line limit",
"A block is created empty",
[] {
block b;
EXPECT(b.empty());
},
"Adding a line makes a block no longer empty",
[] {
block b;
b.add_line(vec{1});
EXPECT(!b.empty());
},
"A block can contain 128 lines",
[] {
block b;
for (int i = 0; i < 128; ++i) {
@ -34,7 +47,7 @@ const lest::test specification[] = {
EXPECT(!b.line_fits(1));
},
"Block size limit",
"A block has a size limit of about 16 kilobyte",
[] {
block b;
for (int i = 0; i < 16; ++i) {
@ -44,30 +57,33 @@ const lest::test specification[] = {
EXPECT(!b.line_fits(400));
},
"Flush",
"Flushing an empty block does nothing",
[] {
block b;
{
tempfile f;
b.flush(f.file());
EXPECT(f.data().empty());
}
for (uint8_t n = 0; n < 10; n += 2) {
vec line = {n, static_cast<uint8_t>(n+1)};
EXPECT(b.line_fits(line.size()));
b.add_line(std::move(line));
}
{
tempfile f;
b.flush(f.file());
EXPECT(( f.data() == vec{'1','2','w',0,5,0,1,2,3,4,5,6,7,8,9} ));
}
{
tempfile f;
b.flush(f.file());
EXPECT(f.data().empty());
}
tempfile f;
b.flush(f.file());
EXPECT(f.data().empty());
},
"Flush() writes the lines to a file with a proper header",
[] {
block b;
for (uint8_t n = 1; n < 6; ++n) {
b.add_line(vec{n, n});
}
tempfile f;
b.flush(f.file());
EXPECT(( f.data() == vec{'1','2','w',0,5,1,1,2,2,3,3,4,4,5,5} ));
},
"After flush() a block is empty again",
[] {
block b;
b.add_line(vec{1});
tempfile f;
b.flush(f.file());
EXPECT(b.empty());
}
};
int main() {

View File

@ -19,7 +19,7 @@
#include <assert.h>
#include <stdint.h>
#include <vector>
#include "src/line.h"
#include "../src/line.h"
typedef std::vector<uint8_t> vec;