1
0
mirror of https://github.com/pdewacht/brlaser synced 2025-04-05 20:36:44 +02:00

Compare commits

...

90 Commits
v1 ... master

Author SHA1 Message Date
Peter De Wachter
2a49e3287c
Merge pull request #133 from yaxollum/fix-mfc-7460dn
Fix MFC-7460DN PPD file name
2023-02-20 21:54:37 +01:00
Peter De Wachter
73b996a049 Github Actions: checkout@v3 2023-02-20 21:26:51 +01:00
Peter De Wachter
e52db5ba46 Github actions: Remove obsolete compilers 2023-02-20 21:24:13 +01:00
Peter De Wachter
48976ab82c
Merge pull request #125 from evanmiller/github-actions
Add support for GitHub Actions
2023-02-20 21:18:44 +01:00
Peter De Wachter
30bd80cb8b Fix build with GCC 13 2023-02-20 21:06:02 +01:00
Peter Ye
ea7e8cd274
Fix MFC-7460DN PPD file name 2021-09-08 14:50:49 -04:00
Evan Miller
df7c37eacf Add libcups2-dev to Linux build environment 2021-05-31 16:28:34 -04:00
Evan Miller
b58a014a51 Fix GitHub Actions script 2021-05-31 16:25:48 -04:00
Evan Miller
bf02b1d7b7 Fix syntax 2021-05-31 16:23:12 -04:00
Evan Miller
9546acc17c Add GitHub Actions for continuous integration 2021-05-31 16:21:33 -04:00
Peter De Wachter
9d7ddda838 Arrange blocks in bands of 128 lines
This is more similar to what the Brother driver does. This might
fix #52, #40, etc.
2020-04-20 21:58:11 +02:00
Peter De Wachter
e21f52f437 Tweak compiler flags 2020-04-20 21:53:43 +02:00
Peter De Wachter
cecfceb27a
Merge pull request #71 from xuzhao9/master
Add Brother DCP-L2520DW
2020-04-18 13:30:25 +02:00
Peter De Wachter
2a5ddf6bd1
Merge pull request #70 from vaukai/vaukai-add-Gentoo-patch-1
Also Gentoo uses brlaser
2020-04-18 13:29:53 +02:00
Peter De Wachter
de0d48dfdb Be tolerant of zero-page jobs
https://github.com/OpenPrinting/cups-filters/issues/117
2020-04-18 10:58:27 +02:00
Peter De Wachter
eae5f9ba98 Add some new printer definitions
Closes #53
Closes #56
Closes #62
Closes #65
2020-04-18 10:24:05 +02:00
xzhao
68dcbc4e38 Add Brother DCP-L2520DW 2020-04-11 08:33:14 -04:00
Volkmar W. Pogatzki
4beeed3733
Update README.md 2020-04-10 13:00:08 +02:00
Peter De Wachter
2f63d0a36c
Merge pull request #55 from nico202/patch-1
Package available on guix, too
2019-11-18 23:04:18 +01:00
Nicolò Balzarotti
e7268ac787
Package available on guix, too
Available here http://guix.gnu.org/packages/brlaser-4-1.779f71e/
2019-11-18 21:05:19 +01:00
Peter De Wachter
23117fe9e0 Bump version number 2019-09-22 21:27:36 +02:00
Peter De Wachter
1b5990560c Version 6 2019-09-22 20:44:17 +02:00
QORTEC
504c00f68e Add Brother HL-2270DW 2019-09-22 20:09:59 +02:00
QORTEC
5d36382350 add gedit backup file to .gitignore (*~) 2019-09-22 20:07:52 +02:00
Peter De Wachter
c08bbc3193 Add a bunch of printers
Closes #33   Brother HL-5030
Closes #39   Brother HL-2140
Closes #44   Brother HL-2220
Closes #45   Brother DCP-L2540D
Closes #46   Brother HL-2030
2019-09-22 19:34:00 +02:00
Peter De Wachter
172c3bf87b Don't compress across bands (#39)
This essentially re-introduces 7ed0d6f, but with a simpler
implementation. Some printers needed it after all.
2019-09-10 23:13:15 +02:00
Peter De Wachter
ff68db0f93 Version 5 2019-05-18 22:56:02 +02:00
Peter De Wachter
dbc897787e Brother HL-1110 2019-05-18 22:38:27 +02:00
Peter De Wachter
17a24ef7a1 Add a bunch of printer stanzas
- Brother DCP-1602 (fixes #42)
- Brother DCP-7060D (fixes #43)
- Brother DCP-L2500D (fixes #35)
- Brother DCP-L2540DW (fixes #32)
- Brother HL-L2340D (fixes #37)
- Brother MFC-1910W (fixes #36)
- Brother MFC-7365DN (fixes #30)
- Brother MFC-7840W (fixes #41)
- Brother MFC-L2710DW (fixes #34)
- Lenovo M7605D (fixes #26)
2019-05-18 22:03:30 +02:00
Peter De Wachter
779f71e80f Reduce max block size to 64 lines (#40)
This fixes HL-1210W, maybe other HL printers as well?
2019-03-25 20:57:51 +01:00
Peter De Wachter
7b4bf383bd O_BINARY
Because it seems people still use OS/2
2019-03-25 20:46:20 +01:00
Peter De Wachter
aa5fb9e2f0 Don't build brdecode by default
It's just a dev tool
2019-03-25 20:24:43 +01:00
Peter De Wachter
7e1cc6911e Update compatibility list.
- Add DCP-7080 (#24)
- Add HL-L2320D (#25)
- Add HL-1200 series (#27)
- Mark HL-L2300D as buggy.
2018-07-04 00:14:44 +02:00
Peter De Wachter
4414717ed4 Avoid overlong encodings, improve compression ratio 2018-07-03 22:42:22 +02:00
Peter De Wachter
41c56264a8 Revert "Do not use delta-encoding across block boundaries"
This reverts commit 7ed0d6f2e8d5a8192c5621898b3ff920c95b66dc.

This was intended as a possible fix for problems with the HL-L2300D
(#4), but it didn't help. And it worsens compression.
2018-07-03 22:37:35 +02:00
Peter De Wachter
7ed0d6f2e8 Do not use delta-encoding across block boundaries
Possible a fix for issue #4

Also: in block.h, rename line_bytes_ to block_size_
2018-04-11 22:45:08 +02:00
Peter De Wachter
4f2f1d606e Add Brother HL-L2360DW (Closes #22) 2018-03-17 12:15:49 +01:00
Peter De Wachter
de26cc4bf0 Add Brother MFC-7240 (Closes #21) 2018-03-13 22:07:13 +01:00
Peter De Wachter
d80491b105 Version 4 2018-02-25 18:47:30 +01:00
Peter De Wachter
a521498233
Merge pull request #19 from StijnDW/master
Allow the user to define cups config variables
2018-02-17 19:04:27 +01:00
Stijn DW
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
Peter De Wachter
ba25b63af6 Add Brother DCP-7040 2018-01-29 08:06:48 +01:00
Peter De Wachter
3946f2e3d6 Add Brother HL-L2300D 2018-01-28 22:34:10 +01:00
Peter De Wachter
0536c6bcad Updated/expanded readme 2018-01-27 00:19:00 +01:00
Peter De Wachter
3008302bb5 Add OpenBSD pledge 2018-01-27 00:18:19 +01:00
Peter De Wachter
39ed3c5708 Cleanups 2018-01-27 00:18:19 +01:00
Peter De Wachter
4209526ef0 setlocale shouldn't be needed 2018-01-27 00:18:19 +01:00
Peter De Wachter
8007996fe7 Fix ppdc warning 2018-01-27 00:18:19 +01:00
Peter De Wachter
cf4fbc86ba CMake: enable assert() for all build types 2018-01-27 00:18:19 +01:00
Peter De Wachter
ab59a83caa Fix brlaser.drv for cmake conversion 2018-01-27 00:18:19 +01:00
Peter De Wachter
6e9793833f CMake conversion 2018-01-27 00:18:19 +01:00
Peter De Wachter
d25ba26132
Merge pull request #17 from blob79/install_ubuntu
Add documentation how to install under Ubuntu
2018-01-25 14:45:46 +01:00
blob79
fbcc6924e8 Add documentation how to install under Ubuntu 2017-12-09 08:04:29 +01:00
Peter De Wachter
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
Peter De Wachter
718053fa36 Add package name to all log messages 2017-10-30 20:07:27 +01:00
Peter De Wachter
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
Peter De Wachter
853db9e5a2 Add Brother MFC-7360N
From Debian bug report #862750; thanks to Mark A. Hershberger.
2017-10-14 21:55:30 +02:00
Peter De Wachter
2fd541c046 Clean up brlaser.drv.in 2017-10-14 21:53:45 +02:00
Peter De Wachter
69cc0bfcc7 Merge remote-tracking branch 'xc-racer99/master' 2017-10-14 21:40:58 +02:00
Peter De Wachter
4fdd8c95a8 Merge pull request #7 from rkreis/dcp1510
Add Brother-DCP1510
2017-10-14 20:57:58 +02:00
Peter De Wachter
5d29d862c7 Merge pull request #5 from lnussel/master
mark DCP-7055W as supported
2017-10-14 20:57:34 +02:00
Peter De Wachter
c58a3b8edd Merge pull request #12 from hollobon/patch-1
Fix typo
2017-10-14 20:52:31 +02:00
Peter De Wachter
c656586451 Merge pull request #9 from cinemast/patch-2
Add missing #include <string>
2017-10-14 20:52:02 +02:00
Pete Hollobon
2859a8a7df Fix typo 2017-08-09 10:32:45 +01:00
xc-racer99
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
xc-racer99
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
xc-racer99
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
Ludwig Nussel
9ccc56e1bc mark DCP-7055W as supported 2016-06-17 10:37:08 +02:00
Peter Spiess-Knafl
93138fec87 Add missing #include <string> 2016-04-25 15:02:37 +02:00
Robin Kreis
d5aa1a55dd Add Brother-DCP1510 2016-03-26 13:24:59 +01:00
Peter De Wachter
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
Peter De Wachter
d85b875627 Use cups-config --ldflags
This fixes link problems on NixOS.
2016-03-02 19:41:44 +01:00
Peter De Wachter
569e3f7766 Reject unexpected raster formats 2015-01-31 23:16:35 +01:00
Peter De Wachter
1474716b27 Misc cleanups, mostly in the test code 2015-01-31 23:13:48 +01:00
Peter De Wachter
4f1a00d46a Rever the readme rename: breaks formatting on Github
This reverts commit 49bfc1be98cc0db9863e469522df39c274fa5ec4.
2014-11-25 00:17:11 +01:00
Peter De Wachter
49bfc1be98 Rename README.md to README 2014-11-25 00:10:23 +01:00
Peter De Wachter
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
Peter De Wachter
1dcd5b445e Fix lest.hpp dependency for the tests. 2014-07-07 13:05:01 +02:00
Peter De Wachter
19edb1767b Kill a harmless dead store
Just because clang's scan-build complained about it.
2014-07-07 13:03:57 +02:00
Peter De Wachter
c3999acbec Version 3 2014-07-07 12:55:16 +02:00
Peter De Wachter
9c4336a8df Updated README 2014-06-30 22:21:22 +02:00
Peter De Wachter
71bb29a3ca Add Brother DCP-7065DN 2014-06-30 22:19:49 +02:00
Peter De Wachter
fa26a6149a Version 2 2014-06-29 11:52:28 +02:00
Peter De Wachter
2e37d9d62a Import lest v1.8.0 2014-06-29 11:50:18 +02:00
Peter De Wachter
77ce307fdb Update gitignore 2014-02-04 22:29:34 +01:00
Peter De Wachter
7bfe0d2846 Reorganize makefile a bit 2014-02-04 22:29:34 +01:00
Peter De Wachter
5159844b03 Add some basic tests 2014-02-04 22:29:27 +01:00
Peter De Wachter
bb1ba17b4f Split out block.h 2014-02-04 21:50:11 +01:00
Peter De Wachter
cd0e4102b4 Distribute the readme file 2014-01-26 20:52:22 +01:00
Peter De Wachter
66ea095ede Changes to support GCC 4.6
GCC 4.6 is the oldest release that can compile this code without significant
changes.
2014-01-26 15:07:53 +01:00
28 changed files with 1573 additions and 722 deletions

39
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,39 @@
name: build
on: [ push, pull_request ]
jobs:
linux:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
compiler: [ clang++, gcc++ ]
steps:
- name: Add repository
run: sudo apt-add-repository -y "ppa:ubuntu-toolchain-r/test"
- name: Install packages
run: sudo apt install libcups2-dev
- uses: actions/checkout@v3
- name: Configure
run: cmake .
- name: Make
run: make
env:
CXX: ${{ matrix.compiler }}
- name: Run tests
run: make check
macos:
runs-on: macos-latest
strategy:
fail-fast: false
matrix:
compiler: [ clang++, gcc++ ]
steps:
- uses: actions/checkout@v3
- name: Configure
run: cmake .
- name: Make
run: make
env:
CXX: ${{ matrix.compiler }}
- name: Run tests
run: make check

23
.gitignore vendored
View File

@ -1,21 +1,2 @@
#
# Autotools
#
/Makefile
/Makefile.in
/aclocal.m4
/autom4te.cache
/build-aux
/config.*
/configure
/stamp-*
.deps/
.dirstamp
#
# Binaries
#
/rastertobrlaser
/brdecode
/brlaser.drv
*.o
*~
build/

140
CMakeLists.txt Normal file
View File

@ -0,0 +1,140 @@
cmake_minimum_required(VERSION 3.1)
project(brlaser CXX)
set(BRLASER_VERSION "6")
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")
extra_cxx_compiler_flag("-Wdate-time")
# Some hardening flags
extra_cxx_compiler_flag("-fstack-protector-strong")
extra_cxx_compiler_flag("-Wformat")
extra_cxx_compiler_flag("-Wformat -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 EXCLUDE_FROM_ALL 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)
add_executable(test_job test/test_job.cc src/job.cc src/line.cc)
enable_testing()
add_test(test_lest test_lest)
add_test(test_line test_line)
add_test(test_block test_block)
add_test(test_job test_job)
# Autotools-style "make check" command
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
add_dependencies(check test_lest test_line test_block test_job)
# Installation
install(
TARGETS rastertobrlaser
DESTINATION "${CUPS_SERVER_BIN}/filter")
install(
FILES "${PROJECT_BINARY_DIR}/brlaser.drv"
DESTINATION "${CUPS_DATA_DIR}/drv")

23
ChangeLog Normal file
View File

@ -0,0 +1,23 @@
brlaser v6 (2019-09-22)
Added support for some more Brother HL-series printers. These printers
had glitched output in earlier releases.
brlaser v5 (2019-05-18)
Fixed problems with Brother HL-series printers in 600 dpi mode. Thanks
to Onno Kortmann for the fix.
Added several printers.
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.
brlaser v1 (2013-12-30)
Initial release.

View File

@ -1,24 +0,0 @@
ACLOCAL_AMFLAGS = -I m4
filter_PROGRAMS = rastertobrlaser
filterdir = $(CUPS_SERVERBIN)/filter
drv_DATA = brlaser.drv
drvdir = $(CUPS_DATADIR)/drv
noinst_PROGRAMS = brdecode
rastertobrlaser_SOURCES = \
src/main.cc \
src/debug.h \
src/debug.cc \
src/job.h \
src/job.cc \
src/line.h \
src/line.cc
rastertobrlaser_CPPFLAGS = $(CUPS_CFLAGS)
rastertobrlaser_LDADD = $(CUPS_LIBS)
brdecode_SOURCES = \
src/brdecode.cc

103
README.md
View File

@ -1,23 +1,98 @@
"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 has been reported to work with these printers:
Requirements
* Brother DCP-1510 series
* Brother DCP-1600 series
* Brother DCP-7030
* Brother DCP-7040
* Brother DCP-7055
* Brother DCP-7055W
* Brother DCP-7060D
* Brother DCP-7065DN
* Brother DCP-7080
* Brother DCP-L2500D series
* Brother DCP-L2520D series
* Brother DCP-L2520DW series
* Brother DCP-L2540DW series
* Brother HL-1110 series
* Brother HL-1200 series
* Brother HL-2030 series
* Brother HL-2140 series
* Brother HL-2220 series
* Brother HL-2270DW series
* Brother HL-5030 series
* Brother HL-L2300D series
* Brother HL-L2320D series
* Brother HL-L2340D series
* Brother HL-L2360D series
* Brother HL-L2375DW series
* Brother HL-L2390DW
* Brother MFC-1910W
* Brother MFC-7240
* Brother MFC-7360N
* Brother MFC-7365DN
* Brother MFC-7420
* Brother MFC-7460DN
* Brother MFC-7840W
* Brother MFC-L2710DW series
* Lenovo M7605D
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. A recent version of GCC or Clang will work.
Some operating systems already ship this driver. This is the case for
at least Debian, Gentoo, Ubuntu, Raspbian, openSUSE, NixOS, Arch Linux
and Guix.
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,266 @@ 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-1600 series"
Attribute "NickName" "" "Brother DCP-1600 series, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,XL2HB;MDL:DCP-1600 series;CLS:PRINTER;CID:Brother Laser Type1;"
PCFileName "br1600.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-7060D"
Attribute "NickName" "" "Brother DCP-7060D, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:DCP-7060D;CLS:PRINTER;CID:Brother Laser Type1;"
Duplex rotated
PCFileName "br7060d.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 "DCP-7080"
Attribute "NickName" "" "Brother DCP-7080, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:DCP-7080;CLS:PRINTER;CID:Brother Laser Type1;"
PCFileName "br7080.ppd"
}
{
ModelName "DCP-7080D"
Attribute "NickName" "" "Brother DCP-7080D, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:DCP-7080D;CLS:PRINTER;CID:Brother Laser Type1;"
Duplex rotated
PCFileName "br7080d.ppd"
}
{
ModelName "DCP-L2500D"
Attribute "NickName" "" "Brother DCP-L2500D series, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:DCP-L2500D series;CLS:PRINTER;CID:Brother Laser Type1;"
Duplex rotated
PCFileName "brl2500d.ppd"
}
{
ModelName "DCP-L2520D"
Attribute "NickName" "" "Brother DCP-L2520D series, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:DCP-L2520D series;CLS:PRINTER;CID:Brother Laser Type1;"
Duplex rotated
PCFileName "brl2520d.ppd"
}
{
ModelName "DCP-L2520DW"
Attribute "NickName" "" "Brother DCP-L2520DW series, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:DCP-L2520DW series;CLS:PRINTER;CID:Brother Laser Type1;"
Duplex rotated
PCFileName "brl2520dw.ppd"
}
{
ModelName "DCP-L2540DW"
Attribute "NickName" "" "Brother DCP-L2540DW series, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:DCP-L2540DW series;CLS:PRINTER;CID:Brother Laser Type1;"
Duplex rotated
PCFileName "brl2540.ppd"
}
{
ModelName "HL-1110"
Attribute "NickName" "" "Brother HL-1110 series, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:HL-1110 series;CLS:PRINTER;CID:Brother Laser Type3;"
Resolution k 1 0 0 0 "300dpi/300 DPI"
PCFileName "br1110.ppd"
}
{
ModelName "HL-1200"
Attribute "NickName" "" "Brother HL-1200 series, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:HL-1200 series;CLS:PRINTER;CID:Brother Laser Type3;"
PCFileName "br1200.ppd"
}
{
ModelName "HL-2030 series"
Attribute "NickName" "" "Brother HL-2030 series, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:HL-2030 series;CLS:PRINTER;"
PCFileName "br2030.ppd"
}
{
ModelName "HL-2140 series"
Attribute "NickName" "" "Brother HL-2140 series, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:HL-2140 series;CLS:PRINTER;"
PCFileName "br2140.ppd"
}
{
ModelName "HL-2220 series"
Attribute "NickName" "" "Brother HL-2220 series, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:HL-2220 series;CLS:PRINTER;"
PCFileName "br2220.ppd"
}
{
ModelName "HL-2270DW series"
Attribute "NickName" "" "Brother HL-2270DW series, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,PCL,PCLXL;MDL:HL-2270DW series;CLS:PRINTER;CID:Brother Laser Type1;"
Resolution k 1 0 0 0 "300dpi/300 DPI"
Duplex rotated
PCFileName "br2270dw.ppd"
}
{
ModelName "HL-5030 series"
Attribute "NickName" "" "Brother HL-5030 series, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,PCL;MDL:HL-5030 series;CLS:PRINTER;"
PCFileName "br5030.ppd"
}
{
ModelName "HL-L2300D"
Attribute "NickName" "" "Brother HL-L2300D series, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:HL-L2300D series;CLS:PRINTER;CID:Brother Laser Type1;"
Duplex rotated
PCFileName "brl2300d.ppd"
}
{
ModelName "HL-L2320D"
Attribute "NickName" "" "Brother HL-L2320D series, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:HL-L2320D series;CLS:PRINTER;CID:Brother Laser Type1;"
Duplex rotated
PCFileName "brl2320d.ppd"
}
{
ModelName "HL-L2340D"
Attribute "NickName" "" "Brother HL-L2340D series, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP,URF;MDL:HL-L2340D series;CLS:PRINTER;CID:Brother Laser Type1;URF:W8,CP1,IS4-1,MT1-3-4-5-8,OB10,PQ4,RS300-600,V1.3,DM1;"
Duplex rotated
PCFileName "brl2340d.ppd"
}
{
ModelName "HL-L2360D"
Attribute "NickName" "" "Brother HL-L2360D series, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,PCL,PCLXL,URF;MDL:HL-L2360D series;CLS:PRINTER;CID:Brother Laser Type1;URF:W8,CP1,IS4-1,MT1-3-4-5-8,OB10,PQ4,RS300-600,V1.3,DM1;"
Duplex rotated
PCFileName "brl2360d.ppd"
}
{
ModelName "HL-L2375DW"
Attribute "NickName" "" "Brother HL-L2375DW series, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,PCL,PCLXL,URF;MDL:HL-L2375DW series;CLS:PRINTER;CID:Brother Laser Type1;URF:W8,CP1,IS4-1,MT1-3-4-5-8,OB10,PQ3-4-5,RS300-600-1200,V1.4,DM1;"
Duplex rotated
PCFileName "brl2375w.ppd"
}
{
ModelName "HL-L2390DW"
Attribute "NickName" "" "Brother HL-L2390DW, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP,URF;MDL:HL-L2390DW;CLS:PRINTER;CID:Brother Laser Type1;URF:W8,CP1,IS4-1,MT1-3-4-5-8,OB10,PQ3-4-5,RS300-600-1200,V1.4,DM1;"
Duplex rotated
PCFileName "brl2390w.ppd"
}
{
ModelName "MFC-1910W"
Attribute "NickName" "" "Brother MFC-1910W, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;MFG:Brother;CMD:PJL,HBP;MDL:MFC-1910W series;CLS:PRINTER;CID:Brother Laser Type1;"
PCFileName "br1910w.ppd"
}
{
ModelName "MFC-7240"
Attribute "NickName" "" "Brother MFC-7240, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;MFG:Brother;CMD:PJL,HBP;MDL:MFC-7240;CLS:PRINTER;CID:Brother Laser Type1;"
PCFileName "br7240.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"
}
{
ModelName "MFC-7365DN"
Attribute "NickName" "" "Brother MFC-7365DN, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:MFC-7365DN;CLS:PRINTER;CID:Brother Laser Type1;"
Resolution k 1 0 0 0 "300dpi/300 DPI"
Duplex rotated
PCFileName "br7365dn.ppd"
}
{
ModelName "MFC-7420"
Attribute "NickName" "" "Brother Brother MFC-7420, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:MFC-7420;CLS:PRINTER;"
PCFileName "br7420.ppd"
}
{
ModelName "MFC-7460DN"
Attribute "NickName" "" "Brother MFC-7460DN, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:MFC-7460DN;CLS:PRINTER;CID:Brother Laser Type1;"
Duplex rotated
PCFileName "br7460dn.ppd"
}
{
ModelName "MFC-L2710DW series"
Attribute "NickName" "" "Brother MFC-L2710DW series, $USING"
Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP,URF;MDL:MFC-L2710DW series;CLS:PRINTER;CID:Brother Laser Type1;URF:W8,CP1,IS4-1,MT1-3-4-5-8,OB10,PQ3-4-5,RS300-600-1200,V1.4,DM1;"
Duplex rotated
PCFileName "brl2710.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], [1], [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
])

65
src/block.h Normal file
View File

@ -0,0 +1,65 @@
// 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/>.
#ifndef BLOCK_H
#define BLOCK_H
#include <assert.h>
#include <stdio.h>
#include <vector>
class block {
public:
block(): line_bytes_(0) {
}
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_.emplace_back(line);
}
bool line_fits(unsigned size) {
return line_bytes_ + size < max_block_size_;
}
void flush(FILE *f) {
if (!empty()) {
fprintf(f, "%dw%c%c",
line_bytes_ + 2, 0,
static_cast<int>(lines_.size()));
for (auto &line : lines_) {
fwrite(line.data(), 1, line.size(), f);
}
line_bytes_ = 0;
lines_.clear();
}
}
private:
static const unsigned max_block_size_ = 16350;
std::vector<std::vector<uint8_t>> lines_;
int line_bytes_;
};
#endif // BLOCK_H

View File

@ -16,10 +16,12 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <algorithm>
#include <exception>
#include <vector>
#include <string>
namespace {
@ -127,9 +129,9 @@ void read_line() {
}
void read_block() {
uint8_t count = get();
unsigned count = get();
count = count * 256 + get();
for (int i = 0; i < count; ++i) {
for (unsigned i = 0; i < count; ++i) {
read_line();
}
}
@ -142,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

@ -20,61 +20,24 @@
#include <algorithm>
#include <vector>
#include "line.h"
#include "block.h"
using std::vector;
namespace {
class block {
public:
void add_line(vector<uint8_t> &&line) {
assert(!line.empty());
line_bytes_ += line.size();
lines_.push_back(line);
}
bool line_fits(unsigned size) {
return lines_.size() != max_lines_per_block_
&& line_bytes_ + size < max_block_size_;
}
void flush(FILE *f) {
if (line_bytes_) {
fprintf(f, "%dw%c%c",
line_bytes_ + 2, 0,
static_cast<int>(lines_.size()));
for (auto &line : lines_) {
fwrite(line.data(), 1, line.size(), f);
}
line_bytes_ = 0;
lines_.clear();
}
}
private:
const unsigned max_block_size_ = 16350;
const unsigned max_lines_per_block_ = 128;
vector<vector<uint8_t>> lines_;
int line_bytes_ = 0;
};
} // namespace
job::job(FILE *out, const std::string &job_name)
: out_(out),
job_name_(job_name),
page_params_() {
page_params_(),
pages_(0) {
// Delete dubious characters from job name
std::replace_if(job_name_.begin(), job_name_.end(), [](char c) {
return c < 32 || c >= 127 || c == '"' || c == '\\';
}, ' ');
begin_job();
}
job::~job() {
end_job();
if (pages_ != 0) {
end_job();
}
}
void job::begin_job() {
@ -111,36 +74,55 @@ 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) {
if (pages_ == 0) {
begin_job();
}
++pages_;
if (!(page_params_ == page_params)) {
page_params_ = page_params;
write_page_header();
}
vector<uint8_t> line(linesize);
vector<uint8_t> reference(linesize);
std::vector<uint8_t> line(linesize);
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) {
vector<uint8_t> encoded = encode_line(line, reference);
if (!block.line_fits(encoded.size())) {
// XXX brother driver uses 128 lines per band
const int lines_per_band = 64;
for (int i = 1; i < lines && nextline(line); ++i) {
std::vector<uint8_t> encoded;
if (i % lines_per_band == 0) {
block.flush(out_);
encoded = encode_line(line);
} else {
encoded = encode_line(line, reference);
if (!block.line_fits(encoded.size())) {
block.flush(out_);
encoded = encode_line(line);
}
}
block.add_line(std::move(encoded));
std::swap(line, reference);

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,17 +45,20 @@ 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);
int pages() const {
return pages_;
}
private:
void begin_job();
void end_job();
@ -59,6 +67,7 @@ class job {
FILE *out_;
std::string job_name_;
page_params page_params_;
int pages_;
};
#endif // JOB_H

View File

@ -145,10 +145,12 @@ vector<uint8_t> encode_line(const vector<uint8_t> &line,
int num_edits = 0;
auto line_it = line.begin();
auto line_end_it =
std::mismatch(line.rbegin(), line.rend(), reference.rbegin()).first.base();
auto ref_it = reference.begin();
while (1) {
int offset = skip_to_next_mismatch(&line_it, line.end(), &ref_it);
if (line_it == line.end()) {
int offset = skip_to_next_mismatch(&line_it, line_end_it, &ref_it);
if (line_it == line_end_it) {
// No more differences, we're done.
break;
}
@ -156,17 +158,17 @@ vector<uint8_t> encode_line(const vector<uint8_t> &line,
if (++num_edits == max_edits) {
// We've run out of edits. Just output the rest of the line in a big
// substitute command.
write_substitute(offset, line_it, line.end(), &output);
write_substitute(offset, line_it, line_end_it, &output);
break;
}
int s = substitute_length(line_it, line.end(), ref_it);
int s = substitute_length(line_it, line_end_it, ref_it);
if (s > 0) {
write_substitute(offset, line_it, std::next(line_it, s), &output);
line_it += s;
ref_it += s;
} else {
int r = repeat_length(line_it, line.end());
int r = repeat_length(line_it, line_end_it);
assert(r >= 2);
write_repeat(offset, r, *line_it, &output);
line_it += r;

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,64 @@
#include "job.h"
#include "debug.h"
#ifndef O_BINARY
#define O_BINARY 0
#endif
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 +99,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 +129,78 @@ 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);
fd = open(job_filename, O_RDONLY | O_BINARY);
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 (pages == 0) {
if (header.cupsBitsPerPixel != 1
|| header.cupsBitsPerColor != 1
|| header.cupsNumColors != 1
|| header.cupsBytesPerLine > 10000) {
fprintf(stderr, "ERROR: " PACKAGE ": Page %d: Bogus raster data.\n", job.pages() + 1);
dump_page_header(header);
return 1;
}
if (job.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);
fprintf(stderr, "PAGE: %d %d\n", job.pages(), header.NumCopies);
}
if (job.pages() == 0) {
fprintf(stderr, "ERROR: " PACKAGE ": No pages were found.\n");
}
}
if (pages == 0) {
fprintf(stderr, "ERROR: No pages were found.");
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;

199
test/lest.hpp Normal file
View File

@ -0,0 +1,199 @@
// Copyright 2013 by Martin Moene
//
// lest is based on ideas by Kevlin Henney, see video at
// http://skillsmatter.com/podcast/agile-testing/kevlin-henney-rethinking-unit-testing-in-c-plus-plus
//
// Distributed under the Boost Software License, Version 1.0:
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#ifndef LEST_LEST_H_INCLUDED
#define LEST_LEST_H_INCLUDED
#include <functional>
#include <iostream>
#include <stdexcept>
#include <string>
#include <cstddef>
#ifndef lest_NO_SHORT_ASSERTION_NAMES
# define EXPECT lest_EXPECT
# define EXPECT_THROWS lest_EXPECT_THROWS
# define EXPECT_THROWS_AS lest_EXPECT_THROWS_AS
#endif
#define lest_EXPECT( expr ) \
try \
{ \
if ( ! (expr) ) \
throw lest::failure{ lest_LOCATION, #expr }; \
} \
catch( lest::failure const & ) \
{ \
throw ; \
} \
catch( std::exception const & e ) \
{ \
throw lest::unexpected{ lest_LOCATION, #expr, lest::with_message( e.what() ) }; \
} \
catch(...) \
{ \
throw lest::unexpected{ lest_LOCATION, #expr, "of unknown type" }; \
}
#define lest_EXPECT_THROWS( expr ) \
for (;;) \
{ \
try { lest::serum( expr ); } catch (...) { break; } \
throw lest::expected{ lest_LOCATION, #expr }; \
}
#define lest_EXPECT_THROWS_AS( expr, excpt ) \
for (;;) \
{ \
try { lest::serum( expr ); } catch ( excpt & ) { break; } catch (...) {} \
throw lest::expected{ lest_LOCATION, #expr, lest::of_type( #excpt ) }; \
}
#define lest_LOCATION lest::location{__FILE__, __LINE__}
namespace lest {
struct test
{
const std::string name;
const std::function<void()> behaviour;
};
struct location
{
const std::string file;
const int line;
location( std::string file, int line )
: file{ file }, line{ line } {}
};
struct comment
{
const std::string text;
comment( std::string text ) : text{ text } {}
explicit operator bool() { return ! text.empty(); }
};
struct message : std::runtime_error
{
const std::string kind;
const location where;
const comment note;
~message() throw() {} // GCC 4.6
message( std::string kind, location where, std::string expr, std::string note = "" )
: std::runtime_error{ expr }, kind{ kind }, where{ where }, note{ note } {}
};
struct failure : message
{
failure( location where, std::string expr )
: message{ "failed", where, expr } {}
};
struct expected : message
{
expected( location where, std::string expr, std::string excpt = "" )
: message{ "failed: didn't get exception", where, expr, excpt } {}
};
struct unexpected : message
{
unexpected( location where, std::string expr, std::string note )
: message{ "failed: got unexpected exception", where, expr, note } {}
};
inline bool serum( bool verum ) { return verum; }
inline std::string with_message( std::string text )
{
return "with message \"" + text + "\"";
}
inline std::string of_type( std::string text )
{
return "of type " + text;
}
inline std::string pluralise( int n, std::string text )
{
return n == 1 ? text : text + "s";
}
inline std::ostream & operator<<( std::ostream & os, comment note )
{
return os << (note ? " " + note.text : "" );
}
inline std::ostream & operator<<( std::ostream & os, location where )
{
#ifdef __GNUG__
return os << where.file << ":" << where.line;
#else
return os << where.file << "(" << where.line << ")";
#endif
}
inline void report( std::ostream & os, message const & e, std::string test )
{
os << e.where << ": " << e.kind << e.note << ": " << test << ": " << e.what() << std::endl;
}
template<std::size_t N>
int run( test const (&specification)[N], std::ostream & os = std::cout )
{
int failures = 0;
for ( auto & testing : specification )
{
try
{
testing.behaviour();
}
catch( message const & e )
{
++failures;
report( os, e, testing.name );
}
}
if ( failures > 0 )
{
os << failures << " out of " << N << " " << pluralise(N, "test") << " failed." << std::endl;
}
return failures;
}
} // namespace lest
#endif // LEST_LEST_H_INCLUDED

55
test/tempfile.h Normal file
View File

@ -0,0 +1,55 @@
// This file is part of the brlaser printer driver.
//
// Copyright 2014 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/>.
#ifndef TEMPFILE_H
#define TEMPFILE_H
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
class tempfile {
public:
explicit tempfile()
: ptr_(0),
size_(0),
file_(open_memstream(&ptr_, &size_)) {
}
~tempfile() {
fclose(file_);
free(ptr_);
}
FILE *file() {
return file_;
}
std::vector<uint8_t> data() {
if (fflush(file_))
return std::vector<uint8_t>();
return std::vector<uint8_t>(ptr_, ptr_ + size_);
}
private:
char *ptr_;
size_t size_;
FILE *file_;
};
#endif // TEMPFILE_H

81
test/test_block.cc Normal file
View File

@ -0,0 +1,81 @@
// This file is part of the brlaser printer driver.
//
// Copyright 2014 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/>.
#include "lest.hpp"
#include <stdint.h>
#include <vector>
#include "tempfile.h"
#include "../src/block.h"
typedef std::vector<uint8_t> vec;
const lest::test specification[] = {
"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 has a size limit of about 16 kilobyte",
[] {
block b;
for (int i = 0; i < 16; ++i) {
EXPECT(b.line_fits(1000));
b.add_line(vec(1000));
}
EXPECT(!b.line_fits(400));
},
"Flushing an empty block does nothing",
[] {
block b;
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() {
return lest::run(specification);
}

35
test/test_job.cc Normal file
View File

@ -0,0 +1,35 @@
// This file is part of the brlaser printer driver.
//
// Copyright 2020 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/>.
#include "lest.hpp"
#include "tempfile.h"
#include "../src/job.h"
const lest::test specification[] = {
"An empty job produces no output",
[] {
tempfile f;
{
job j(f.file(), "name");
}
EXPECT(f.data().empty());
},
};
int main() {
return lest::run(specification);
}

291
test/test_lest.cc Normal file
View File

@ -0,0 +1,291 @@
// Copyright 2013 by Martin Moene
//
// Distributed under the Boost Software License, Version 1.0:
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#include "lest.hpp"
#include <sstream>
using namespace lest;
const lest::test specification[] =
{
"Function to suppress warning \"expression has no effect\" acts as identity function", []
{
EXPECT( false == serum( false ) );
EXPECT( true == serum( true ) );
},
"Function with_message() returns correct string", []
{
std::string msg = "Let writing tests become irresistibly easy and attractive.";
EXPECT( "with message \"" + msg + "\"" == with_message( msg ) );
},
"Function of_type() returns correct string", []
{
std::string msg = "this_type";
EXPECT( "of type " + msg == of_type( msg ) );
},
"Function pluralise() adds 's' except for 1 item", []
{
std::string word = "hammer";
EXPECT( word == pluralise( 1, word ) );
for ( auto i : {0,2,3,4,5,6,7,8,9,10,11,12} )
EXPECT( word + "s" == pluralise( i, word ) );
},
"Location constructs properly", []
{
char const * file = __FILE__; int line = __LINE__;
location where{ file, line };
EXPECT( file == where.file );
EXPECT( line == where.line );
},
"Comment constructs properly", []
{
std::string text = __FILE__;
comment note = text;
EXPECT( text == note.text );
},
"Comment converted to bool indicates absence or presence of comment", []
{
EXPECT( false == bool( comment( "") ) );
EXPECT( true == bool( comment("x") ) );
},
"Failure exception type constructs and prints properly", []
{
std::string name = "test-name";
failure msg( location{"filename.cpp", 765}, "expression" );
std::ostringstream os;
report( os, msg, name );
#ifndef __GNUG__
EXPECT( os.str() == "filename.cpp(765): failed: test-name: expression\n" );
#else
EXPECT( os.str() == "filename.cpp:765: failed: test-name: expression\n" );
#endif
},
"Expected exception type constructs and prints properly", []
{
std::string name = "test-name";
expected msg( location{"filename.cpp", 765}, "expression" );
std::ostringstream os;
report( os, msg, name );
#ifndef __GNUG__
EXPECT( os.str() == "filename.cpp(765): failed: didn't get exception: test-name: expression\n" );
#else
EXPECT( os.str() == "filename.cpp:765: failed: didn't get exception: test-name: expression\n" );
#endif
},
"Unexpected exception type constructs and prints properly", []
{
std::string name = "test-name";
unexpected msg( location{"filename.cpp", 765}, "expression", "exception-type" );
std::ostringstream os;
report( os, msg, name );
#ifndef __GNUG__
EXPECT( os.str() == "filename.cpp(765): failed: got unexpected exception exception-type: test-name: expression\n" );
#else
EXPECT( os.str() == "filename.cpp:765: failed: got unexpected exception exception-type: test-name: expression\n" );
#endif
},
"Expect generates no message exception for a succeeding test", []
{
test pass = { "P", [] { EXPECT( true ); } };
try { pass.behaviour(); }
catch(...) { throw failure(location{__FILE__,__LINE__}, "unexpected error generated"); }
},
"Expect generates a message exception for a failing test", []
{
test fail = { "F", [] { EXPECT( false ); } };
for (;;)
{
try { fail.behaviour(); } catch ( message & ) { break; }
throw failure(location{__FILE__,__LINE__}, "no error generated");
}
},
"Expect succeeds for success (true) and failure (false)", []
{
test pass[] = {{ "P", [] { EXPECT( true ); } }};
test fail[] = {{ "F", [] { EXPECT( false ); } }};
std::ostringstream os;
EXPECT( 0 == run( pass, os ) );
EXPECT( 1 == run( fail, os ) );
},
"Expect succeeds for integer comparation", []
{
test pass [] = {{ "P" , [] { EXPECT( 7 == 7 ); EXPECT( 7 != 8 );
EXPECT( 7 >= 6 ); EXPECT( 7 <= 8 );
EXPECT( 7 > 6 ); EXPECT( 7 < 8 ); } }};
test fail_1[] = {{ "F1", [] { EXPECT( 7 == 8 ); } }};
test fail_2[] = {{ "F2", [] { EXPECT( 7 != 7 ); } }};
test fail_3[] = {{ "F3", [] { EXPECT( 7 <= 6 ); } }};
test fail_4[] = {{ "F4", [] { EXPECT( 7 >= 8 ); } }};
test fail_5[] = {{ "F5", [] { EXPECT( 7 < 6 ); } }};
test fail_6[] = {{ "F6", [] { EXPECT( 7 > 8 ); } }};
std::ostringstream os;
EXPECT( 0 == run( pass , os ) );
EXPECT( 1 == run( fail_1, os ) );
EXPECT( 1 == run( fail_2, os ) );
EXPECT( 1 == run( fail_3, os ) );
EXPECT( 1 == run( fail_4, os ) );
EXPECT( 1 == run( fail_5, os ) );
EXPECT( 1 == run( fail_6, os ) );
},
"Expect succeeds for string comparation", []
{
std::string a("a"); std::string b("b");
test pass [] = {{ "P" , [=]() { EXPECT( a == a ); EXPECT( a != b );
EXPECT( b >= a ); EXPECT( a <= b );
EXPECT( b > a ); EXPECT( a < b ); } }};
test fail_1[] = {{ "F1", [=]() { EXPECT( a == b ); } }};
test fail_2[] = {{ "F2", [=]() { EXPECT( a != a ); } }};
test fail_3[] = {{ "F3", [=]() { EXPECT( b <= a ); } }};
test fail_4[] = {{ "F4", [=]() { EXPECT( a >= b ); } }};
test fail_5[] = {{ "F5", [=]() { EXPECT( b < a ); } }};
test fail_6[] = {{ "F6", [=]() { EXPECT( a > b ); } }};
std::ostringstream os;
EXPECT( 0 == run( pass , os ) );
EXPECT( 1 == run( fail_1, os ) );
EXPECT( 1 == run( fail_2, os ) );
EXPECT( 1 == run( fail_3, os ) );
EXPECT( 1 == run( fail_4, os ) );
EXPECT( 1 == run( fail_5, os ) );
EXPECT( 1 == run( fail_6, os ) );
},
"Function run() returns the right failure count", []
{
test pass [] = {{ "P" , [] { EXPECT( 1==1 ); } }};
test fail_1[] = {{ "F1", [] { EXPECT( 0==1 ); } }};
test fail_3[] = {{ "F1", [] { EXPECT( 0==1 ); } },
{ "F2", [] { EXPECT( 0==1 ); } },
{ "F3", [] { EXPECT( 0==1 ); } },};
std::ostringstream os;
EXPECT( 0 == run( pass , os ) );
EXPECT( 1 == run( fail_1, os ) );
EXPECT( 3 == run( fail_3, os ) );
},
"Expect succeeds with an unexpected standard exception", []
{
std::string text = "hello-world";
test pass[] = {{ "P", [=]() { EXPECT( (throw std::runtime_error(text), true) ); } }};
std::ostringstream os;
EXPECT( 1 == run( pass, os ) );
EXPECT( std::string::npos != os.str().find(text) );
},
"Expect succeeds with an unexpected non-standard exception", []
{
test pass[] = {{ "P", [] { EXPECT( (throw 77, true) ); } }};
std::ostringstream os;
EXPECT( 1 == run( pass, os ) );
},
"Expect_throws succeeds with an expected standard exception", []
{
std::string text = "hello-world";
test pass[] = {{ "P", [=]() { EXPECT_THROWS( (throw std::runtime_error(text), true) ); } }};
test fail[] = {{ "F", [ ]() { EXPECT_THROWS( true ); } }};
std::ostringstream os;
EXPECT( 0 == run( pass, os ) );
EXPECT( 1 == run( fail, os ) );
},
"Expect_throws succeeds with an expected non-standard exception", []
{
test pass[] = {{ "P", [] { EXPECT_THROWS( (throw 77, true) ); } }};
test fail[] = {{ "F", [] { EXPECT_THROWS( true ); } }};
std::ostringstream os;
EXPECT( 0 == run( pass, os ) );
EXPECT( 1 == run( fail, os ) );
},
"Expect_throws_as succeeds with a specific expected standard exception", []
{
test pass[] = {{ "P", [] { EXPECT_THROWS_AS( (throw std::bad_alloc(), true), std::bad_alloc ); } }};
test fail[] = {{ "F", [] { EXPECT_THROWS_AS( (throw std::bad_alloc(), true), std::runtime_error ); } }};
std::ostringstream os;
EXPECT( 0 == run( pass, os ) );
EXPECT( 1 == run( fail, os ) );
},
"Expect_throws_as succeeds with a specific expected non-standard exception", []
{
test pass[] = {{ "P", [] { EXPECT_THROWS_AS( (throw 77, true), int ); } }};
test fail[] = {{ "F", [] { EXPECT_THROWS_AS( (throw 77, true), std::runtime_error ); } }};
std::ostringstream os;
EXPECT( 0 == run( pass, os ) );
EXPECT( 1 == run( fail, os ) );
},
};
int main()
{
return lest::run( specification );
}
// cl -nologo -Wall -EHsc test_lest.cpp && test_lest
// g++ -Wall -Wextra -Weffc++ -std=c++11 -o test_lest.exe test_lest.cpp && test_lest

150
test/test_line.cc Normal file
View File

@ -0,0 +1,150 @@
// This file is part of the brlaser printer driver.
//
// Copyright 2014 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/>.
#include "lest.hpp"
#include <assert.h>
#include <stdint.h>
#include <vector>
#include "../src/line.h"
typedef std::vector<uint8_t> vec;
uint8_t sub(uint8_t offset, uint8_t count) {
assert(offset < 16);
assert(count < 8);
return (offset << 3) | count;
}
uint8_t rep(uint8_t offset, uint8_t count) {
assert(offset < 4);
assert(count < 32);
return 128 | (offset << 5) | count;
}
const lest::test specification[] = {
"Don't crash on zero-length lines",
[] {
EXPECT(( encode_line(vec{}) == vec{0xFF} ));
EXPECT(( encode_line(vec{}, vec{}) == vec{0xFF} ));
},
"Encoding an initial blank line",
[] {
EXPECT(( encode_line(vec{0,0,0}) == vec{0xFF} ));
},
"Encoding an initial non-blank line",
[] {
EXPECT(( encode_line(vec{1,2,3}) == (vec{1,sub(0,2),1,2,3}) ));
},
"Encoding a (non-initial) blank line",
[] {
EXPECT(( encode_line(vec{0,0,0}, vec{1,2,3}) == vec{0xFF} ));
},
"Encoding a repeated line",
[] {
EXPECT(( encode_line(vec{1,2,3}, vec{1,2,3}) == vec{0} ));
},
"Using a subsitute command",
[] {
EXPECT(( encode_line(vec{0,0,1,2,3,0,0}, vec(7)) == vec{1,sub(2,2),1,2,3} ));
},
"Using a repeat command",
[] {
EXPECT(( encode_line(vec{0,0,1,1,0,0}, vec(6)) == vec{1,rep(2,0),1} ));
},
"Repeat command followed by substitute command",
[] {
EXPECT(( encode_line(vec{1,1,1,2,3}, vec(5)) == vec{2,rep(0,1),1,sub(0,1),2,3} ));
},
"Substitute comand followed by repeat command",
[] {
EXPECT(( encode_line(vec{3,2,1,1,1}, vec(5)) == vec{2,sub(0,1),3,2,rep(0,1),1} ));
},
"Substitute with an unmodified byte in the middle",
[] {
EXPECT(( encode_line(vec{1,2,3,0,1,2,3}, vec(7)) == vec{1,sub(0,6),1,2,3,0,1,2,3} ));
},
"Substitue with two unmodified bytes in the middle",
[] {
EXPECT(( encode_line(vec{1,2,3,0,0,1,2,3}, vec(8)) == vec{2,sub(0,2),1,2,3,sub(2,2),1,2,3} ));
},
"Repeat with an unmodified byte in the middle",
[] {
EXPECT(( encode_line(vec{1,1,1,0,1,1,1}, vec(7)) == vec{2,rep(0,1),1,rep(1,1),1} ));
},
"254 edits needed for a single line",
[] {
vec line, result;
for (int i = 0; i < 254; ++i)
line.insert(line.end(), {0,0,1});
result.push_back(254);
for (int i = 0; i < 254; ++i)
result.insert(result.end(), {sub(2,0),1});
EXPECT(( encode_line(line, vec(line.size())) == result ));
},
"Give up if more than 254 edits needed...",
[] {
vec line, result;
for (int i = 0; i < 255; ++i)
line.insert(line.end(), {0,0,1});
result.push_back(254);
for (int i = 0; i < 253; ++i)
result.insert(result.end(), {sub(2,0),1});
result.insert(result.end(), {sub(2,3),1,0,0,1});
EXPECT(( encode_line(line, vec(line.size())) == result ));
},
"Repeat command with overflow bytes",
[] {
vec line(3, 0);
line.insert(line.end(), 512, 1);
vec ref(line.size(), 0);
vec expected{1,rep(3,31),0,255,224,1};
EXPECT(encode_line(line, ref) == expected);
},
"Substitute command with overflow bytes",
[] {
vec expected{1,sub(15,7),255,0,255,237};
vec line(270, 0);
for (int i = 0; i < 250; ++i) {
expected.insert(expected.end(), {1,2});
line.insert(line.end(), {1,2});
}
vec ref(line.size(), 0);
EXPECT(encode_line(line, ref) == expected);
},
};
int main() {
return lest::run(specification);
}