2010-10-12 15:57:08 +02:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
re-base on ALv2 code. Includes (at least) relevant parts of:
linecap: Reintegrating finished LineCap feature
Patch contributed by Regina Henschel
http://svn.apache.org/viewvc?view=revision&revision=1232507
Patches contributed by Sven Jacobi
impress212: #i81610# fixed animation export
http://svn.apache.org/viewvc?view=revision&revision=1167620
impress212: drawinglayer gbuild environment changes
http://svn.apache.org/viewvc?view=revision&revision=1167627
http://svn.apache.org/viewvc?view=revision&revision=1167628
impress212: DffPropSet -> minor code improvements, removing table
http://svn.apache.org/viewvc?view=revision&revision=1167634
impress212: #158494# fixed excel import (text rotation)
http://svn.apache.org/viewvc?view=revision&revision=1167638
Patches contributed by Armin Le Grand
Svg: Reintegrated Svg replacement from /branches/alg/svgreplavement
http://svn.apache.org/viewvc?view=revision&revision=1220836
#118728# changed indentifying definitions for Svg file detection
http://svn.apache.org/viewvc?view=revision&revision=1229961
#118838# LineGeometry creation for complicated cases optimized to
create single Polygons
http://svn.apache.org/viewvc?view=revision&revision=1236232
#119176# corrected file type detection for SVG for svg files
without xml header
http://svn.apache.org/viewvc?view=revision&revision=1309445
#118728# Extended Svg file detection
http://svn.apache.org/viewvc?view=revision&revision=1230531
#118529# solve break converters and convert commands for OLEs and images
http://svn.apache.org/viewvc?view=revision&revision=1186168
svg: added WaE changes from branch svgreplacement to trunc
http://svn.apache.org/viewvc?view=revision&revision=1222974
svg: corrected missing member initialization
http://svn.apache.org/viewvc?view=revision&revision=1226134
fix for #118525#: Using primitives for chart sub-geometry visualisation
http://svn.apache.org/viewvc?view=revision&revision=1226879
#118898# Adapted ImpGraphic::ImplGetBitmap to correctly convert
metafiles to bitmapEx ...
http://svn.apache.org/viewvc?view=revision&revision=1293316
fix for #118525#: removed no longer used variable maOriginalMapMode, one
more exception eliminated
http://svn.apache.org/viewvc?view=revision&revision=1227097
#16758# Added buffering to the VDev usages of the VclProcessor2D derivates...
http://svn.apache.org/viewvc?view=revision&revision=1229521
#116758# Secured VDev buffer device to Vcl deinit
http://svn.apache.org/viewvc?view=revision&revision=1230574
#116758# added remembering allocated VDevs for VDevBuffer to be able to also
delete these when vcl goes down; it should never happen, but You never know
http://svn.apache.org/viewvc?view=revision&revision=1230927
#118730# Changed SvgClipPathNode to use MaskPrimitive2D for primitive
representation instead of TransparencePrimitive2D
http://svn.apache.org/viewvc?view=revision&revision=1231198
#118822# secured 3D geometry creation (slices) by subdividing the 2D
source polyPolygon early
http://svn.apache.org/viewvc?view=revision&revision=1234749
#118829# enhanced Svg gradient quality, obstacles avoided
http://svn.apache.org/viewvc?view=revision&revision=1235361
#118834# Unified usage of TextBreakupHelper as single tooling class
for i18n text primitive breakup
http://svn.apache.org/viewvc?view=revision&revision=1236110
#118853# added square pixel size limit to conversion of
TransparencePrimitive2D to Metafile action
http://svn.apache.org/viewvc?view=revision&revision=1237656
#118824# coreccted mirroring and boundrect when the graphicmanager
is used for bitmap output
http://svn.apache.org/viewvc?view=revision&revision=1240097
#115092# Corrected VclProcessor2D::RenderPolygonStrokePrimitive2D for
various optimization scenarios
http://svn.apache.org/viewvc?view=revision&revision=1241434
#118783# Corrected errors in ID strings, corrected Svg line/fill export,
corrected polygon close state
http://svn.apache.org/viewvc?view=revision&revision=1232006
#118796# corrected null-pointer usage in SVG text exporter
http://svn.apache.org/viewvc?view=revision&revision=1240262
#118729# Use GraphicStreamUrl and GraphicUrl to allow multi image
import with linked graphics, too
http://svn.apache.org/viewvc?view=revision&revision=1229962
#118898# corrected error in GDIMetaFile::GetBoundRect in handling
MetaFloatTransparentAction
http://svn.apache.org/viewvc?view=revision&revision=1293349
#118855# Corrected handling of possibly created empty clipRegions
after PolyPolygon clipping
http://svn.apache.org/viewvc?view=revision&revision=1237725
#115962# Better (but not yet optimal, see comments in task) handling
of MetaFloatTransparentAction in PDF export
http://svn.apache.org/viewvc?view=revision&revision=1241078
IP clearance: #118466# This patch removes librsvg, libcroco, libgsf, ...
http://svn.apache.org/viewvc?view=revision&revision=1200879
118779# Added svg content streaming in/out to ImpGraphic stream operators
http://svn.apache.org/viewvc?view=revision&revision=1231908
linecap: correctons for WaE and mac drawing
http://svn.apache.org/viewvc?view=revision&revision=1232793
svg: uses current system Dpi for Svg replacement image creation
http://svn.apache.org/viewvc?view=revision&revision=1233948
Patches contributed by Mathias Bauer (and others)
gnumake4 work variously
http://svn.apache.org/viewvc?view=revision&revision=1394326
http://svn.apache.org/viewvc?view=revision&revision=1396797
http://svn.apache.org/viewvc?view=revision&revision=1397315
http://svn.apache.org/viewvc?view=revision&revision=1394326
Remove duplicate header includes.
cws mba34issues01: #i117720#: convert assertion into warning
http://svn.apache.org/viewvc?view=revision&revision=1172352
118485 - Styles for OLEs are not saved. Submitted by Armin Le Grand.
http://svn.apache.org/viewvc?view=revision&revision=1182166
cws mba34issues01: #i117714#: remove assertion
http://svn.apache.org/viewvc?view=revision&revision=1172357
Patch contributed by Jurgen Schmidt
add some additional checks to ensure proper reading operations
http://svn.apache.org/viewvc?view=revision&revision=1209022
mostly prefer our stream / bounds checking work.
Patches contributed by Herbert Duerr
#i118816# add clarifying comment regarding Font::*Color*() methods
http://svn.apache.org/viewvc?view=revision&revision=1233833
extend macro->string handling for empty strings
http://svn.apache.org/viewvc?view=revision&revision=1175801
avoid magic constants for SALCOLOR_NONE
http://svn.apache.org/viewvc?view=revision&revision=1177543
initialize slant properly in ImplFontMetricData constructor (author=iorsh)
http://svn.apache.org/viewvc?view=revision&revision=1177551
#i118675# make check for extension updates more stable
http://svn.apache.org/viewvc?view=revision&revision=1214797
#a118617# remove VBasicEventListener.dll binary
There are no known users depending on its CLSID
http://svn.apache.org/viewvc?view=revision&revision=1203697
Patches contributed by Ariel Constenla-Haile
Fix build breaker on Linux/gcc
http://svn.apache.org/viewvc?view=revision&revision=1221104
Fix crash when trying to instantiate css.graphic.GraphicRasterizer_RSVG
http://svn.apache.org/viewvc?view=revision&revision=1215559
Patches contributed by Oliver-Rainer Wittmann
sw34bf06: #i117962# - method <SwFlyFrm::IsPaint(..)> - consider
instances of <SwFlyDrawObj>
http://svn.apache.org/viewvc?view=revision&revision=1172120
sw34bf06: #i117783# - Writer's implementation of XPagePrintable -
apply print settings to new printing routines
http://svn.apache.org/viewvc?view=revision&revision=1172115
gnumake4 work variously from Hans-Joachim Lankenau
http://svn.apache.org/viewvc?view=revision&revision=1397315
http://svn.apache.org/viewvc?view=revision&revision=1396797
http://svn.apache.org/viewvc?view=revision&revision=1396782
http://svn.apache.org/viewvc?view=revision&revision=1394707
plus some amount of re-splitting of legacy headers.
Patch contributed by Pavel Janik
WaE: Remove unused variables.
http://svn.apache.org/viewvc?view=revision&revision=1230697
Patches contributed by Takashi Ono
mingwport35: i#117795: MinGW port fix for vcl2gnumake
http://svn.apache.org/viewvc?view=revision&revision=1172091
mingwport35: i#117795: MinGW port fix for vcl2gnumake
http://svn.apache.org/viewvc?view=revision&revision=1172091
Patch contributed by Christian Lippka
impress212: #i98044# re enable Text menu for outline and title shapes
http://svn.apache.org/viewvc?view=revision&revision=1167639
Patch contributed by Andre Fischer
118674: Made category B code optional and disabled by default.
http://svn.apache.org/viewvc?view=revision&revision=1215131
118881: Ignore empty paragraphs after bullets.
http://svn.apache.org/viewvc?view=revision&revision=1296205
Patches contributed by Philipp Lohmann
ooo340fixes: #i117780# use rtl allocator
http://svn.apache.org/viewvc?view=revision&revision=1172087
ooo34gsl02: #i117807# fix an off by one error (index actually
inside the pfb section header)
http://svn.apache.org/viewvc?view=revision&revision=1167576
various cleanups, related compilation fixes, warning cleanups, re-working
of obsolete stl template pieces to use boost instead, changed string
classes, re-adapt KDE about data, about dialog, fixing warnings,
and other fixes & improvements.
Disable svg import / render for about/ branding code-paths for now.
Restore full icon theme set.
Remove OS/2 conditionals and sources.
Remove conflicting gtk/full-screen monitors support.
Retain existing svg rasterizer files - temporarily disabled.
Standardize stringificaiton and fixup dllpostfix issues.
Rename SvgGradientHelper::== to equalTo to avoid overloading issues.
Use the flat GdiPlus API for LineCaps calls.
2012-10-09 12:22:23 +01:00
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*
|
|
|
|
* This file incorporates work covered by the following license notice:
|
|
|
|
*
|
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
|
|
* with this work for additional information regarding copyright
|
|
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy of
|
|
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
|
|
*/
|
2006-09-16 12:27:12 +00:00
|
|
|
|
2017-09-11 14:27:57 +02:00
|
|
|
#include <type_traits>
|
2002-04-03 12:24:35 +00:00
|
|
|
#include <math.h>
|
New loplugin:unsignedcompare
"Find explicit casts from signed to unsigned integer in comparison against
unsigned integer, where the cast is presumably used to avoid warnings about
signed vs. unsigned comparisons, and could thus be replaced with
o3tl::make_unsigned for clairty." (compilerplugins/clang/unsignedcompare.cxx)
o3tl::make_unsigned requires its argument to be non-negative, and there is a
chance that some original code like
static_cast<sal_uInt32>(n) >= c
used the explicit cast to actually force a (potentially negative) value of
sal_Int32 to be interpreted as an unsigned sal_uInt32, rather than using the
cast to avoid a false "signed vs. unsigned comparison" warning in a case where
n is known to be non-negative. It appears that restricting this plugin to non-
equality comparisons (<, >, <=, >=) and excluding equality comparisons (==, !=)
is a useful heuristic to avoid such false positives. The only remainging false
positive I found was 0288c8ffecff4956a52b9147d441979941e8b87f "Rephrase cast
from sal_Int32 to sal_uInt32".
But which of course does not mean that there were no further false positivies
that I missed. So this commit may accidentally introduce some false hits of the
assert in o3tl::make_unsigned. At least, it passed a full (Linux ASan+UBSan
--enable-dbgutil) `make check && make screenshot`.
It is by design that o3tl::make_unsigned only accepts signed integer parameter
types (and is not defined as a nop for unsigned ones), to avoid unnecessary uses
which would in general be suspicious. But the STATIC_ARRAY_SELECT macro in
include/oox/helper/helper.hxx is used with both signed and unsigned types, so
needs a little oox::detail::make_unsigned helper function for now. (The
ultimate fix being to get rid of the macro in the first place.)
Change-Id: Ia4adc9f44c70ad1dfd608784cac39ee922c32175
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/87556
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2020-01-27 09:30:39 +01:00
|
|
|
|
|
|
|
#include <o3tl/safeint.hxx>
|
2008-01-14 14:03:00 +00:00
|
|
|
#include <osl/file.h>
|
2015-04-22 09:42:28 +02:00
|
|
|
#include <sal/log.hxx>
|
2000-09-18 15:18:56 +00:00
|
|
|
#include <tools/stream.hxx>
|
2014-11-14 11:06:44 +00:00
|
|
|
#include <unotools/tempfile.hxx>
|
2017-10-23 22:41:56 +02:00
|
|
|
#include "sane.hxx"
|
2000-09-18 15:18:56 +00:00
|
|
|
#include <dlfcn.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <sys/time.h>
|
2005-08-18 07:13:56 +00:00
|
|
|
#include <sal/config.h>
|
2010-10-16 20:56:57 +01:00
|
|
|
#include <sal/macros.h>
|
2015-06-15 17:58:15 +09:00
|
|
|
#include <memory>
|
2000-09-18 15:18:56 +00:00
|
|
|
|
2016-03-09 17:29:55 +05:30
|
|
|
#if (OSL_DEBUG_LEVEL > 0) || defined DBG_UTIL
|
2000-09-18 15:18:56 +00:00
|
|
|
#include <stdarg.h>
|
|
|
|
#define dump_state( a, b, c, d ) fprintf( stderr, a, b, c, d );
|
|
|
|
#else
|
|
|
|
#define dump_state( a, b, c, d ) ;
|
|
|
|
#endif
|
2018-10-09 10:28:48 +02:00
|
|
|
static void dbg_msg( const char* pString, ... )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
2016-03-09 17:29:55 +05:30
|
|
|
#if (OSL_DEBUG_LEVEL > 0) || defined DBG_UTIL
|
2000-09-18 15:18:56 +00:00
|
|
|
va_list ap;
|
|
|
|
va_start( ap, pString );
|
|
|
|
vfprintf( stderr, pString, ap );
|
|
|
|
va_end( ap );
|
2008-01-14 14:03:00 +00:00
|
|
|
#else
|
|
|
|
(void)pString;
|
2000-09-18 15:18:56 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#define FAIL_SHUTDOWN_STATE( x, y, z ) \
|
|
|
|
if( x != SANE_STATUS_GOOD ) \
|
|
|
|
{ \
|
|
|
|
dump_state( "%s returned error %d (%s)\n", \
|
|
|
|
y, x, p_strstatus( x ) ); \
|
|
|
|
DeInit(); \
|
|
|
|
return z; \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define FAIL_STATE( x, y, z ) \
|
|
|
|
if( x != SANE_STATUS_GOOD ) \
|
|
|
|
{ \
|
|
|
|
dump_state( "%s returned error %d (%s)\n", \
|
|
|
|
y, x, p_strstatus( x ) ); \
|
|
|
|
return z; \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define DUMP_STATE( x, y ) \
|
|
|
|
if( x != SANE_STATUS_GOOD ) \
|
|
|
|
{ \
|
|
|
|
dump_state( "%s returned error %d (%s)\n", \
|
|
|
|
y, x, p_strstatus( x ) ); \
|
|
|
|
}
|
|
|
|
|
|
|
|
int Sane::nRefCount = 0;
|
2015-11-10 10:14:53 +01:00
|
|
|
oslModule Sane::pSaneLib = nullptr;
|
2000-09-18 15:18:56 +00:00
|
|
|
SANE_Int Sane::nVersion = 0;
|
2015-11-10 10:14:53 +01:00
|
|
|
SANE_Device** Sane::ppDevices = nullptr;
|
2000-09-18 15:18:56 +00:00
|
|
|
int Sane::nDevices = 0;
|
|
|
|
|
|
|
|
SANE_Status (*Sane::p_init)( SANE_Int*,
|
2015-11-10 10:14:53 +01:00
|
|
|
SANE_Auth_Callback ) = nullptr;
|
|
|
|
void (*Sane::p_exit)() = nullptr;
|
2000-09-18 15:18:56 +00:00
|
|
|
SANE_Status (*Sane::p_get_devices)( const SANE_Device***,
|
2015-11-10 10:14:53 +01:00
|
|
|
SANE_Bool ) = nullptr;
|
|
|
|
SANE_Status (*Sane::p_open)( SANE_String_Const, SANE_Handle ) = nullptr;
|
|
|
|
void (*Sane::p_close)( SANE_Handle ) = nullptr;
|
2000-09-18 15:18:56 +00:00
|
|
|
const SANE_Option_Descriptor* (*Sane::p_get_option_descriptor)(
|
2015-11-10 10:14:53 +01:00
|
|
|
SANE_Handle, SANE_Int ) = nullptr;
|
2000-09-18 15:18:56 +00:00
|
|
|
SANE_Status (*Sane::p_control_option)( SANE_Handle, SANE_Int,
|
|
|
|
SANE_Action, void*,
|
2015-11-10 10:14:53 +01:00
|
|
|
SANE_Int* ) = nullptr;
|
2000-09-18 15:18:56 +00:00
|
|
|
SANE_Status (*Sane::p_get_parameters)( SANE_Handle,
|
2015-11-10 10:14:53 +01:00
|
|
|
SANE_Parameters* ) = nullptr;
|
|
|
|
SANE_Status (*Sane::p_start)( SANE_Handle ) = nullptr;
|
2000-09-18 15:18:56 +00:00
|
|
|
SANE_Status (*Sane::p_read)( SANE_Handle, SANE_Byte*, SANE_Int,
|
2015-11-10 10:14:53 +01:00
|
|
|
SANE_Int* ) = nullptr;
|
|
|
|
void (*Sane::p_cancel)( SANE_Handle ) = nullptr;
|
|
|
|
SANE_Status (*Sane::p_set_io_mode)( SANE_Handle, SANE_Bool ) = nullptr;
|
|
|
|
SANE_Status (*Sane::p_get_select_fd)( SANE_Handle, SANE_Int* ) = nullptr;
|
|
|
|
SANE_String_Const (*Sane::p_strstatus)( SANE_Status ) = nullptr;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
2014-04-30 11:46:15 +02:00
|
|
|
static bool bSaneSymbolLoadFailed = false;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
2008-01-14 14:03:00 +00:00
|
|
|
inline oslGenericFunction Sane::LoadSymbol( const char* pSymbolname )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
2008-01-14 14:03:00 +00:00
|
|
|
oslGenericFunction pFunction = osl_getAsciiFunctionSymbol( pSaneLib, pSymbolname );
|
|
|
|
if( ! pFunction )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
2008-01-14 14:03:00 +00:00
|
|
|
fprintf( stderr, "Could not load symbol %s\n",
|
|
|
|
pSymbolname );
|
2014-04-30 11:46:15 +02:00
|
|
|
bSaneSymbolLoadFailed = true;
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
2008-01-14 14:03:00 +00:00
|
|
|
return pFunction;
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SANE_Status Sane::ControlOption( int nOption, SANE_Action nAction,
|
|
|
|
void* pData )
|
|
|
|
{
|
|
|
|
SANE_Int nInfo = 0;
|
|
|
|
|
2018-01-12 20:24:28 +01:00
|
|
|
SANE_Status nStatus = p_control_option( maHandle, static_cast<SANE_Int>(nOption),
|
2000-09-18 15:18:56 +00:00
|
|
|
nAction, pData, &nInfo );
|
|
|
|
DUMP_STATE( nStatus, "sane_control_option" );
|
2016-03-09 17:29:55 +05:30
|
|
|
#if OSL_DEBUG_LEVEL > 0
|
2000-09-18 15:18:56 +00:00
|
|
|
if( nStatus != SANE_STATUS_GOOD )
|
|
|
|
{
|
2008-07-31 11:58:34 +00:00
|
|
|
const char* pAction = "Unknown";
|
2000-09-18 15:18:56 +00:00
|
|
|
switch( nAction )
|
|
|
|
{
|
|
|
|
case SANE_ACTION_GET_VALUE:
|
|
|
|
pAction = "SANE_ACTION_GET_VALUE";break;
|
|
|
|
case SANE_ACTION_SET_VALUE:
|
|
|
|
pAction = "SANE_ACTION_SET_VALUE";break;
|
|
|
|
case SANE_ACTION_SET_AUTO:
|
|
|
|
pAction = "SANE_ACTION_SET_AUTO";break;
|
|
|
|
}
|
|
|
|
dbg_msg( "Option: \"%s\" action: %s\n",
|
2013-04-07 12:06:47 +02:00
|
|
|
OUStringToOString(GetOptionName(nOption), osl_getThreadTextEncoding()).getStr(),
|
2000-09-18 15:18:56 +00:00
|
|
|
pAction );
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if( nInfo & SANE_INFO_RELOAD_OPTIONS )
|
|
|
|
ReloadOptions();
|
|
|
|
return nStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
Sane::Sane() :
|
|
|
|
mnOptions( 0 ),
|
2008-01-14 14:03:00 +00:00
|
|
|
mnDevice( -1 ),
|
2015-11-10 10:14:53 +01:00
|
|
|
maHandle( nullptr )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
|
|
|
if( ! nRefCount || ! pSaneLib )
|
|
|
|
Init();
|
|
|
|
nRefCount++;
|
|
|
|
};
|
|
|
|
|
|
|
|
Sane::~Sane()
|
|
|
|
{
|
|
|
|
if( IsOpen() )
|
|
|
|
Close();
|
|
|
|
nRefCount--;
|
|
|
|
if( ! nRefCount && pSaneLib )
|
|
|
|
DeInit();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sane::Init()
|
|
|
|
{
|
2013-04-07 12:06:47 +02:00
|
|
|
OUString sSaneLibName( "libsane" SAL_DLLEXTENSION );
|
2008-01-14 14:03:00 +00:00
|
|
|
pSaneLib = osl_loadModule( sSaneLibName.pData, SAL_LOADMODULE_LAZY );
|
2003-03-25 15:04:55 +00:00
|
|
|
if( ! pSaneLib )
|
2008-01-14 14:03:00 +00:00
|
|
|
{
|
2013-11-04 11:55:50 +02:00
|
|
|
sSaneLibName = "libsane" SAL_DLLEXTENSION ".1";
|
2008-01-14 14:03:00 +00:00
|
|
|
pSaneLib = osl_loadModule( sSaneLibName.pData, SAL_LOADMODULE_LAZY );
|
|
|
|
}
|
2001-04-27 12:50:55 +00:00
|
|
|
// try reasonable places that might not be in the library search path
|
|
|
|
if( ! pSaneLib )
|
2008-01-14 14:03:00 +00:00
|
|
|
{
|
2013-04-07 12:06:47 +02:00
|
|
|
OUString sSaneLibSystemPath( "/usr/local/lib/libsane" SAL_DLLEXTENSION );
|
2008-01-14 14:03:00 +00:00
|
|
|
osl_getFileURLFromSystemPath( sSaneLibSystemPath.pData, &sSaneLibName.pData );
|
|
|
|
pSaneLib = osl_loadModule( sSaneLibName.pData, SAL_LOADMODULE_LAZY );
|
|
|
|
}
|
|
|
|
|
2000-09-18 15:18:56 +00:00
|
|
|
if( pSaneLib )
|
|
|
|
{
|
2014-04-30 11:46:15 +02:00
|
|
|
bSaneSymbolLoadFailed = false;
|
2015-01-17 18:45:03 +01:00
|
|
|
p_init = reinterpret_cast<SANE_Status(*)(SANE_Int*, SANE_Auth_Callback )>(
|
|
|
|
LoadSymbol( "sane_init" ));
|
|
|
|
p_exit = reinterpret_cast<void(*)()>(
|
|
|
|
LoadSymbol( "sane_exit" ));
|
|
|
|
p_get_devices = reinterpret_cast<SANE_Status(*)(const SANE_Device***,
|
|
|
|
SANE_Bool )>(
|
|
|
|
LoadSymbol( "sane_get_devices" ));
|
|
|
|
p_open = reinterpret_cast<SANE_Status(*)(SANE_String_Const, SANE_Handle )>(
|
|
|
|
LoadSymbol( "sane_open" ));
|
|
|
|
p_close = reinterpret_cast<void(*)(SANE_Handle)>(
|
|
|
|
LoadSymbol( "sane_close" ));
|
|
|
|
p_get_option_descriptor = reinterpret_cast<const SANE_Option_Descriptor*(*)(SANE_Handle,
|
|
|
|
SANE_Int)>(
|
|
|
|
LoadSymbol( "sane_get_option_descriptor" ));
|
|
|
|
p_control_option = reinterpret_cast<SANE_Status(*)(SANE_Handle, SANE_Int,
|
|
|
|
SANE_Action, void*, SANE_Int*)>(
|
|
|
|
LoadSymbol( "sane_control_option" ));
|
|
|
|
p_get_parameters = reinterpret_cast<SANE_Status(*)(SANE_Handle,SANE_Parameters*)>(
|
|
|
|
LoadSymbol( "sane_get_parameters" ));
|
|
|
|
p_start = reinterpret_cast<SANE_Status(*)(SANE_Handle)>(
|
|
|
|
LoadSymbol( "sane_start" ));
|
|
|
|
p_read = reinterpret_cast<SANE_Status(*)(SANE_Handle, SANE_Byte*,
|
|
|
|
SANE_Int, SANE_Int* )>(
|
|
|
|
LoadSymbol( "sane_read" ));
|
|
|
|
p_cancel = reinterpret_cast<void(*)(SANE_Handle)>(
|
|
|
|
LoadSymbol( "sane_cancel" ));
|
|
|
|
p_set_io_mode = reinterpret_cast<SANE_Status(*)(SANE_Handle, SANE_Bool)>(
|
|
|
|
LoadSymbol( "sane_set_io_mode" ));
|
|
|
|
p_get_select_fd = reinterpret_cast<SANE_Status(*)(SANE_Handle, SANE_Int*)>(
|
|
|
|
LoadSymbol( "sane_get_select_fd" ));
|
|
|
|
p_strstatus = reinterpret_cast<SANE_String_Const(*)(SANE_Status)>(
|
|
|
|
LoadSymbol( "sane_strstatus" ));
|
2000-09-18 15:18:56 +00:00
|
|
|
if( bSaneSymbolLoadFailed )
|
|
|
|
DeInit();
|
|
|
|
else
|
|
|
|
{
|
2015-11-10 10:14:53 +01:00
|
|
|
SANE_Status nStatus = p_init( &nVersion, nullptr );
|
2000-09-18 15:18:56 +00:00
|
|
|
FAIL_SHUTDOWN_STATE( nStatus, "sane_init", );
|
2015-06-02 11:26:25 +02:00
|
|
|
nStatus = p_get_devices( const_cast<const SANE_Device***>(&ppDevices),
|
2000-09-18 15:18:56 +00:00
|
|
|
SANE_FALSE );
|
|
|
|
FAIL_SHUTDOWN_STATE( nStatus, "sane_get_devices", );
|
2008-10-10 13:02:43 +00:00
|
|
|
for( nDevices = 0 ; ppDevices[ nDevices ]; nDevices++ ) ;
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
}
|
2016-03-09 17:29:55 +05:30
|
|
|
#if (OSL_DEBUG_LEVEL > 0) || defined DBG_UTIL
|
2000-09-18 15:18:56 +00:00
|
|
|
else
|
2005-08-18 07:13:56 +00:00
|
|
|
fprintf( stderr, "libsane%s could not be opened: %s\n", SAL_DLLEXTENSION,
|
2000-09-18 15:18:56 +00:00
|
|
|
dlerror() );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sane::DeInit()
|
|
|
|
{
|
|
|
|
if( pSaneLib )
|
|
|
|
{
|
|
|
|
p_exit();
|
2008-01-14 14:03:00 +00:00
|
|
|
osl_unloadModule( pSaneLib );
|
2015-11-10 10:14:53 +01:00
|
|
|
pSaneLib = nullptr;
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sane::ReloadDevices()
|
|
|
|
{
|
|
|
|
if( IsOpen() )
|
|
|
|
Close();
|
|
|
|
DeInit();
|
|
|
|
Init();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sane::ReloadOptions()
|
|
|
|
{
|
|
|
|
if( ! IsOpen() )
|
|
|
|
return;
|
|
|
|
|
2012-03-19 22:43:30 +01:00
|
|
|
const SANE_Option_Descriptor* pZero = p_get_option_descriptor( maHandle, 0 );
|
2000-09-18 15:18:56 +00:00
|
|
|
SANE_Word pOptions[2];
|
|
|
|
SANE_Status nStatus = p_control_option( maHandle, 0, SANE_ACTION_GET_VALUE,
|
2015-11-10 10:14:53 +01:00
|
|
|
static_cast<void*>(pOptions), nullptr );
|
2000-09-18 15:18:56 +00:00
|
|
|
if( nStatus != SANE_STATUS_GOOD )
|
|
|
|
fprintf( stderr, "Error: sane driver returned %s while reading number of options !\n", p_strstatus( nStatus ) );
|
|
|
|
|
|
|
|
mnOptions = pOptions[ 0 ];
|
New loplugin:unsignedcompare
"Find explicit casts from signed to unsigned integer in comparison against
unsigned integer, where the cast is presumably used to avoid warnings about
signed vs. unsigned comparisons, and could thus be replaced with
o3tl::make_unsigned for clairty." (compilerplugins/clang/unsignedcompare.cxx)
o3tl::make_unsigned requires its argument to be non-negative, and there is a
chance that some original code like
static_cast<sal_uInt32>(n) >= c
used the explicit cast to actually force a (potentially negative) value of
sal_Int32 to be interpreted as an unsigned sal_uInt32, rather than using the
cast to avoid a false "signed vs. unsigned comparison" warning in a case where
n is known to be non-negative. It appears that restricting this plugin to non-
equality comparisons (<, >, <=, >=) and excluding equality comparisons (==, !=)
is a useful heuristic to avoid such false positives. The only remainging false
positive I found was 0288c8ffecff4956a52b9147d441979941e8b87f "Rephrase cast
from sal_Int32 to sal_uInt32".
But which of course does not mean that there were no further false positivies
that I missed. So this commit may accidentally introduce some false hits of the
assert in o3tl::make_unsigned. At least, it passed a full (Linux ASan+UBSan
--enable-dbgutil) `make check && make screenshot`.
It is by design that o3tl::make_unsigned only accepts signed integer parameter
types (and is not defined as a nop for unsigned ones), to avoid unnecessary uses
which would in general be suspicious. But the STATIC_ARRAY_SELECT macro in
include/oox/helper/helper.hxx is used with both signed and unsigned types, so
needs a little oox::detail::make_unsigned helper function for now. (The
ultimate fix being to get rid of the macro in the first place.)
Change-Id: Ia4adc9f44c70ad1dfd608784cac39ee922c32175
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/87556
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2020-01-27 09:30:39 +01:00
|
|
|
if( o3tl::make_unsigned(pZero->size) > sizeof( SANE_Word ) )
|
2018-07-21 11:09:44 +02:00
|
|
|
fprintf( stderr, "driver returned number of options with larger size than SANE_Word!!!\n" );
|
2018-05-04 14:02:49 +02:00
|
|
|
mppOptions.reset(new const SANE_Option_Descriptor*[ mnOptions ]);
|
2012-03-19 22:43:30 +01:00
|
|
|
mppOptions[ 0 ] = pZero;
|
2000-09-18 15:18:56 +00:00
|
|
|
for( int i = 1; i < mnOptions; i++ )
|
2015-03-26 15:28:40 +01:00
|
|
|
mppOptions[ i ] = p_get_option_descriptor( maHandle, i );
|
2000-09-18 15:18:56 +00:00
|
|
|
|
2015-11-10 10:14:53 +01:00
|
|
|
CheckConsistency( nullptr, true );
|
2000-09-18 15:18:56 +00:00
|
|
|
|
2015-09-17 09:25:04 +02:00
|
|
|
maReloadOptionsLink.Call( *this );
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
|
2014-04-30 11:46:15 +02:00
|
|
|
bool Sane::Open( const char* name )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
2015-06-02 11:26:25 +02:00
|
|
|
SANE_Status nStatus = p_open( reinterpret_cast<SANE_String_Const>(name), &maHandle );
|
2014-04-30 11:46:15 +02:00
|
|
|
FAIL_STATE( nStatus, "sane_open", false );
|
2000-09-18 15:18:56 +00:00
|
|
|
|
|
|
|
ReloadOptions();
|
|
|
|
|
|
|
|
if( mnDevice == -1 )
|
|
|
|
{
|
2013-04-07 12:06:47 +02:00
|
|
|
OString aDevice( name );
|
2011-10-02 13:28:04 +02:00
|
|
|
for( int i = 0; i < nDevices; i++ )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
2017-07-06 13:10:19 +02:00
|
|
|
if( aDevice == ppDevices[i]->name )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
|
|
|
mnDevice = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-30 11:46:15 +02:00
|
|
|
return true;
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
|
2014-04-30 11:46:15 +02:00
|
|
|
bool Sane::Open( int n )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
|
|
|
if( n >= 0 && n < nDevices )
|
|
|
|
{
|
|
|
|
mnDevice = n;
|
2015-03-26 15:28:40 +01:00
|
|
|
return Open( ppDevices[n]->name );
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
2014-04-30 11:46:15 +02:00
|
|
|
return false;
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Sane::Close()
|
|
|
|
{
|
|
|
|
if( maHandle )
|
|
|
|
{
|
|
|
|
p_close( maHandle );
|
2018-05-04 14:02:49 +02:00
|
|
|
mppOptions.reset();
|
2015-11-10 10:14:53 +01:00
|
|
|
maHandle = nullptr;
|
2000-09-18 15:18:56 +00:00
|
|
|
mnDevice = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int Sane::GetOptionByName( const char* rName )
|
|
|
|
{
|
|
|
|
int i;
|
2013-04-07 12:06:47 +02:00
|
|
|
OString aOption( rName );
|
2000-09-18 15:18:56 +00:00
|
|
|
for( i = 0; i < mnOptions; i++ )
|
|
|
|
{
|
2017-07-06 13:10:19 +02:00
|
|
|
if( mppOptions[i]->name && aOption == mppOptions[i]->name )
|
2000-09-18 15:18:56 +00:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-04-30 11:46:15 +02:00
|
|
|
bool Sane::GetOptionValue( int n, bool& rRet )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
|
|
|
if( ! maHandle || mppOptions[n]->type != SANE_TYPE_BOOL )
|
2014-04-30 11:46:15 +02:00
|
|
|
return false;
|
2000-09-18 15:18:56 +00:00
|
|
|
SANE_Word nRet;
|
|
|
|
SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, &nRet );
|
|
|
|
if( nStatus != SANE_STATUS_GOOD )
|
2014-04-30 11:46:15 +02:00
|
|
|
return false;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
|
|
|
rRet = nRet;
|
2014-04-30 11:46:15 +02:00
|
|
|
return true;
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
|
2014-04-30 11:46:15 +02:00
|
|
|
bool Sane::GetOptionValue( int n, OString& rRet )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
2014-04-30 11:46:15 +02:00
|
|
|
bool bSuccess = false;
|
2000-09-18 15:18:56 +00:00
|
|
|
if( ! maHandle || mppOptions[n]->type != SANE_TYPE_STRING )
|
2014-04-30 11:46:15 +02:00
|
|
|
return false;
|
2015-06-15 17:58:15 +09:00
|
|
|
std::unique_ptr<char[]> pRet(new char[mppOptions[n]->size+1]);
|
2014-04-02 16:08:04 +09:00
|
|
|
SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pRet.get() );
|
2000-09-18 15:18:56 +00:00
|
|
|
if( nStatus == SANE_STATUS_GOOD )
|
|
|
|
{
|
2014-04-30 11:46:15 +02:00
|
|
|
bSuccess = true;
|
2014-04-02 16:08:04 +09:00
|
|
|
rRet = pRet.get();
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
return bSuccess;
|
|
|
|
}
|
|
|
|
|
2014-04-30 11:46:15 +02:00
|
|
|
bool Sane::GetOptionValue( int n, double& rRet, int nElement )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
2014-04-30 11:46:15 +02:00
|
|
|
bool bSuccess = false;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
|
|
|
if( ! maHandle || ( mppOptions[n]->type != SANE_TYPE_INT &&
|
|
|
|
mppOptions[n]->type != SANE_TYPE_FIXED ) )
|
2014-04-30 11:46:15 +02:00
|
|
|
return false;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
2015-06-15 17:58:15 +09:00
|
|
|
std::unique_ptr<SANE_Word[]> pRet(new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)]);
|
2014-04-02 16:08:04 +09:00
|
|
|
SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pRet.get() );
|
2000-09-18 15:18:56 +00:00
|
|
|
if( nStatus == SANE_STATUS_GOOD )
|
|
|
|
{
|
2014-04-30 11:46:15 +02:00
|
|
|
bSuccess = true;
|
2000-09-18 15:18:56 +00:00
|
|
|
if( mppOptions[n]->type == SANE_TYPE_INT )
|
2018-01-12 20:24:28 +01:00
|
|
|
rRet = static_cast<double>(pRet[ nElement ]);
|
2000-09-18 15:18:56 +00:00
|
|
|
else
|
|
|
|
rRet = SANE_UNFIX( pRet[nElement] );
|
|
|
|
}
|
|
|
|
return bSuccess;
|
|
|
|
}
|
|
|
|
|
2014-04-30 11:46:15 +02:00
|
|
|
bool Sane::GetOptionValue( int n, double* pSet )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
2020-05-29 11:34:00 +02:00
|
|
|
if( ! maHandle || ( mppOptions[n]->type != SANE_TYPE_FIXED &&
|
|
|
|
mppOptions[n]->type != SANE_TYPE_INT ) )
|
2014-04-30 11:46:15 +02:00
|
|
|
return false;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
2015-06-15 17:58:15 +09:00
|
|
|
std::unique_ptr<SANE_Word[]> pFixedSet(new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)]);
|
2014-04-02 16:08:04 +09:00
|
|
|
SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pFixedSet.get() );
|
2000-09-18 15:18:56 +00:00
|
|
|
if( nStatus != SANE_STATUS_GOOD )
|
2014-04-30 11:46:15 +02:00
|
|
|
return false;
|
2008-01-14 14:03:00 +00:00
|
|
|
for( size_t i = 0; i <mppOptions[n]->size/sizeof(SANE_Word); i++ )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
|
|
|
if( mppOptions[n]->type == SANE_TYPE_FIXED )
|
|
|
|
pSet[i] = SANE_UNFIX( pFixedSet[i] );
|
|
|
|
else
|
2018-01-12 20:24:28 +01:00
|
|
|
pSet[i] = static_cast<double>(pFixedSet[i]);
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
2014-04-30 11:46:15 +02:00
|
|
|
return true;
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
|
2015-10-07 12:05:17 +02:00
|
|
|
void Sane::SetOptionValue( int n, bool bSet )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
|
|
|
if( ! maHandle || mppOptions[n]->type != SANE_TYPE_BOOL )
|
2015-10-07 12:05:17 +02:00
|
|
|
return;
|
2000-09-18 15:18:56 +00:00
|
|
|
SANE_Word nRet = bSet ? SANE_TRUE : SANE_FALSE;
|
2015-10-07 12:05:17 +02:00
|
|
|
ControlOption( n, SANE_ACTION_SET_VALUE, &nRet );
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
|
2020-12-11 17:44:34 +01:00
|
|
|
void Sane::SetOptionValue( int n, std::u16string_view rSet )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
|
|
|
if( ! maHandle || mppOptions[n]->type != SANE_TYPE_STRING )
|
2015-10-07 12:05:17 +02:00
|
|
|
return;
|
2013-04-07 12:06:47 +02:00
|
|
|
OString aSet(OUStringToOString(rSet, osl_getThreadTextEncoding()));
|
2015-10-07 12:05:17 +02:00
|
|
|
ControlOption( n, SANE_ACTION_SET_VALUE, const_cast<char *>(aSet.getStr()) );
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
|
2015-10-07 12:05:17 +02:00
|
|
|
void Sane::SetOptionValue( int n, double fSet, int nElement )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
|
|
|
if( ! maHandle || ( mppOptions[n]->type != SANE_TYPE_INT &&
|
|
|
|
mppOptions[n]->type != SANE_TYPE_FIXED ) )
|
2015-10-07 12:05:17 +02:00
|
|
|
return;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
|
|
|
if( mppOptions[n]->size/sizeof(SANE_Word) > 1 )
|
|
|
|
{
|
2015-06-15 17:58:15 +09:00
|
|
|
std::unique_ptr<SANE_Word[]> pSet(new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)]);
|
2015-10-07 12:05:17 +02:00
|
|
|
SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pSet.get() );
|
2000-09-18 15:18:56 +00:00
|
|
|
if( nStatus == SANE_STATUS_GOOD )
|
|
|
|
{
|
|
|
|
pSet[nElement] = mppOptions[n]->type == SANE_TYPE_INT ?
|
2018-01-12 20:24:28 +01:00
|
|
|
static_cast<SANE_Word>(fSet) : SANE_FIX( fSet );
|
2015-10-07 12:05:17 +02:00
|
|
|
ControlOption( n, SANE_ACTION_SET_VALUE, pSet.get() );
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SANE_Word nSetTo =
|
|
|
|
mppOptions[n]->type == SANE_TYPE_INT ?
|
2018-01-12 20:24:28 +01:00
|
|
|
static_cast<SANE_Word>(fSet) : SANE_FIX( fSet );
|
2000-09-18 15:18:56 +00:00
|
|
|
|
2015-10-07 12:05:17 +02:00
|
|
|
ControlOption( n, SANE_ACTION_SET_VALUE, &nSetTo );
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-02 12:09:52 +02:00
|
|
|
void Sane::SetOptionValue( int n, double const * pSet )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
|
|
|
if( ! maHandle || ( mppOptions[n]->type != SANE_TYPE_INT &&
|
|
|
|
mppOptions[n]->type != SANE_TYPE_FIXED ) )
|
2015-10-07 12:05:17 +02:00
|
|
|
return;
|
2015-06-15 17:58:15 +09:00
|
|
|
std::unique_ptr<SANE_Word[]> pFixedSet(new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)]);
|
2008-01-14 14:03:00 +00:00
|
|
|
for( size_t i = 0; i < mppOptions[n]->size/sizeof(SANE_Word); i++ )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
|
|
|
if( mppOptions[n]->type == SANE_TYPE_FIXED )
|
|
|
|
pFixedSet[i] = SANE_FIX( pSet[i] );
|
|
|
|
else
|
2018-01-12 20:24:28 +01:00
|
|
|
pFixedSet[i] = static_cast<SANE_Word>(pSet[i]);
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
2015-10-07 12:05:17 +02:00
|
|
|
ControlOption( n, SANE_ACTION_SET_VALUE, pFixedSet.get() );
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
|
2019-11-16 21:00:53 +01:00
|
|
|
namespace {
|
|
|
|
|
2000-09-18 15:18:56 +00:00
|
|
|
enum FrameStyleType {
|
|
|
|
FrameStyle_BW, FrameStyle_Gray, FrameStyle_RGB, FrameStyle_Separated
|
|
|
|
};
|
|
|
|
|
2019-11-16 21:00:53 +01:00
|
|
|
}
|
|
|
|
|
2000-09-18 15:18:56 +00:00
|
|
|
#define BYTE_BUFFER_SIZE 32768
|
|
|
|
|
2018-10-09 10:28:48 +02:00
|
|
|
static sal_uInt8 ReadValue( FILE* fp, int depth )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
|
|
|
if( depth == 16 )
|
|
|
|
{
|
2011-01-14 12:13:45 +01:00
|
|
|
sal_uInt16 nWord;
|
2000-09-18 15:18:56 +00:00
|
|
|
// data always come in native byte order !
|
|
|
|
// 16 bits is not really supported by backends as of now
|
|
|
|
// e.g. UMAX Astra 1200S delivers 16 bit but in BIGENDIAN
|
|
|
|
// against SANE documentation (xscanimage gets the same result
|
|
|
|
// as we do
|
2012-04-21 14:29:14 +02:00
|
|
|
size_t items_read = fread( &nWord, 1, 2, fp );
|
|
|
|
|
2012-04-21 22:24:03 +01:00
|
|
|
if (items_read != 2)
|
2012-04-21 14:29:14 +02:00
|
|
|
{
|
2012-04-21 22:24:03 +01:00
|
|
|
SAL_WARN( "extensions.scanner", "short read, abandoning" );
|
|
|
|
return 0;
|
2012-04-21 14:29:14 +02:00
|
|
|
}
|
2012-04-21 22:24:03 +01:00
|
|
|
|
2018-01-12 20:24:28 +01:00
|
|
|
return static_cast<sal_uInt8>( nWord / 256 );
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
2011-01-14 12:13:45 +01:00
|
|
|
sal_uInt8 nByte;
|
2012-04-21 14:29:14 +02:00
|
|
|
size_t items_read = fread( &nByte, 1, 1, fp );
|
2012-04-21 22:24:03 +01:00
|
|
|
if (items_read != 1)
|
2012-04-21 14:29:14 +02:00
|
|
|
{
|
2012-04-21 22:24:03 +01:00
|
|
|
SAL_WARN( "extensions.scanner", "short read, abandoning" );
|
|
|
|
return 0;
|
2012-04-21 14:29:14 +02:00
|
|
|
}
|
2000-09-18 15:18:56 +00:00
|
|
|
return nByte;
|
|
|
|
}
|
|
|
|
|
2014-04-30 11:46:15 +02:00
|
|
|
bool Sane::CheckConsistency( const char* pMes, bool bInit )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
2015-11-10 10:14:53 +01:00
|
|
|
static const SANE_Option_Descriptor** pDescArray = nullptr;
|
|
|
|
static const SANE_Option_Descriptor* pZero = nullptr;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
|
|
|
if( bInit )
|
|
|
|
{
|
2018-05-04 14:02:49 +02:00
|
|
|
pDescArray = mppOptions.get();
|
2000-09-18 15:18:56 +00:00
|
|
|
if( mppOptions )
|
2012-03-19 22:43:30 +01:00
|
|
|
pZero = mppOptions[0];
|
2014-04-30 11:46:15 +02:00
|
|
|
return true;
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
|
2014-04-30 11:46:15 +02:00
|
|
|
bool bConsistent = true;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
2018-05-04 14:02:49 +02:00
|
|
|
if( pDescArray != mppOptions.get() )
|
2014-04-30 11:46:15 +02:00
|
|
|
bConsistent = false;
|
2000-09-18 15:18:56 +00:00
|
|
|
if( pZero != mppOptions[0] )
|
2014-04-30 11:46:15 +02:00
|
|
|
bConsistent = false;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
|
|
|
if( ! bConsistent )
|
|
|
|
dbg_msg( "Sane is not consistent. (%s)\n", pMes );
|
|
|
|
|
|
|
|
return bConsistent;
|
|
|
|
}
|
|
|
|
|
2014-04-30 11:46:15 +02:00
|
|
|
bool Sane::Start( BitmapTransporter& rBitmap )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
|
|
|
int nStream = 0, nLine = 0, i = 0;
|
|
|
|
SANE_Parameters aParams;
|
|
|
|
FrameStyleType eType = FrameStyle_Gray;
|
2014-04-30 11:46:15 +02:00
|
|
|
bool bSuccess = true;
|
|
|
|
bool bWidthSet = false;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
|
|
|
if( ! maHandle )
|
2014-04-30 11:46:15 +02:00
|
|
|
return false;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
2002-03-28 15:45:33 +00:00
|
|
|
int nWidthMM = 0;
|
|
|
|
int nHeightMM = 0;
|
2014-12-12 19:07:13 +01:00
|
|
|
double fTLx, fTLy, fResl = 0.0;
|
2002-03-28 15:45:33 +00:00
|
|
|
int nOption;
|
2020-04-15 09:02:32 +02:00
|
|
|
nOption = GetOptionByName( "tl-x" );
|
|
|
|
if( nOption != -1 &&
|
2015-08-12 15:09:57 +02:00
|
|
|
GetOptionValue( nOption, fTLx ) &&
|
2002-03-28 15:45:33 +00:00
|
|
|
GetOptionUnit( nOption ) == SANE_UNIT_MM )
|
|
|
|
{
|
2014-12-12 19:07:13 +01:00
|
|
|
double fBRx;
|
2020-04-15 09:02:32 +02:00
|
|
|
nOption = GetOptionByName( "br-x" );
|
|
|
|
if( nOption != -1 &&
|
2015-08-12 15:09:57 +02:00
|
|
|
GetOptionValue( nOption, fBRx ) &&
|
2002-03-28 15:45:33 +00:00
|
|
|
GetOptionUnit( nOption ) == SANE_UNIT_MM )
|
|
|
|
{
|
2018-01-12 20:24:28 +01:00
|
|
|
nWidthMM = static_cast<int>(fabs(fBRx - fTLx));
|
2002-03-28 15:45:33 +00:00
|
|
|
}
|
|
|
|
}
|
2020-04-15 09:02:32 +02:00
|
|
|
nOption = GetOptionByName( "tl-y" );
|
|
|
|
if( nOption != -1 &&
|
2015-08-12 15:09:57 +02:00
|
|
|
GetOptionValue( nOption, fTLy ) &&
|
2002-03-28 15:45:33 +00:00
|
|
|
GetOptionUnit( nOption ) == SANE_UNIT_MM )
|
|
|
|
{
|
2014-12-12 19:07:13 +01:00
|
|
|
double fBRy;
|
2020-04-15 09:02:32 +02:00
|
|
|
nOption = GetOptionByName( "br-y" );
|
|
|
|
if( nOption != -1 &&
|
2015-08-12 15:09:57 +02:00
|
|
|
GetOptionValue( nOption, fBRy ) &&
|
2002-03-28 15:45:33 +00:00
|
|
|
GetOptionUnit( nOption ) == SANE_UNIT_MM )
|
|
|
|
{
|
2018-01-12 20:24:28 +01:00
|
|
|
nHeightMM = static_cast<int>(fabs(fBRy - fTLy));
|
2002-03-28 15:45:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if( ( nOption = GetOptionByName( "resolution" ) ) != -1 )
|
2014-11-01 20:28:37 +00:00
|
|
|
(void)GetOptionValue( nOption, fResl );
|
2002-03-28 15:45:33 +00:00
|
|
|
|
2018-10-23 08:23:32 +02:00
|
|
|
std::unique_ptr<sal_uInt8[]> pBuffer;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
|
|
|
SANE_Status nStatus = SANE_STATUS_GOOD;
|
|
|
|
|
|
|
|
rBitmap.lock();
|
|
|
|
SvMemoryStream& aConverter = rBitmap.getStream();
|
|
|
|
aConverter.Seek( 0 );
|
2015-01-05 08:47:31 +02:00
|
|
|
aConverter.SetEndian( SvStreamEndian::LITTLE );
|
2000-09-18 15:18:56 +00:00
|
|
|
|
|
|
|
// write bitmap stream header
|
2014-01-08 08:48:26 +02:00
|
|
|
aConverter.WriteChar( 'B' ).WriteChar( 'M' );
|
2014-09-25 20:19:30 +02:00
|
|
|
aConverter.WriteUInt32( 0 );
|
|
|
|
aConverter.WriteUInt32( 0 );
|
|
|
|
aConverter.WriteUInt32( 60 );
|
2000-09-18 15:18:56 +00:00
|
|
|
|
|
|
|
// write BITMAPINFOHEADER
|
2014-09-25 20:19:30 +02:00
|
|
|
aConverter.WriteUInt32( 40 );
|
|
|
|
aConverter.WriteUInt32( 0 ); // fill in width later
|
|
|
|
aConverter.WriteUInt32( 0 ); // fill in height later
|
2014-09-25 17:56:24 +02:00
|
|
|
aConverter.WriteUInt16( 1 );
|
2000-09-18 15:18:56 +00:00
|
|
|
// create header for 24 bits
|
|
|
|
// correct later if necessary
|
2014-09-25 17:56:24 +02:00
|
|
|
aConverter.WriteUInt16( 24 );
|
2014-09-25 20:19:30 +02:00
|
|
|
aConverter.WriteUInt32( 0 );
|
|
|
|
aConverter.WriteUInt32( 0 );
|
|
|
|
aConverter.WriteUInt32( 0 );
|
|
|
|
aConverter.WriteUInt32( 0 );
|
|
|
|
aConverter.WriteUInt32( 0 );
|
|
|
|
aConverter.WriteUInt32( 0 );
|
2000-09-18 15:18:56 +00:00
|
|
|
|
|
|
|
for( nStream=0; nStream < 3 && bSuccess ; nStream++ )
|
|
|
|
{
|
|
|
|
nStatus = p_start( maHandle );
|
|
|
|
DUMP_STATE( nStatus, "sane_start" );
|
|
|
|
CheckConsistency( "sane_start" );
|
|
|
|
if( nStatus == SANE_STATUS_GOOD )
|
|
|
|
{
|
|
|
|
nStatus = p_get_parameters( maHandle, &aParams );
|
|
|
|
DUMP_STATE( nStatus, "sane_get_parameters" );
|
|
|
|
CheckConsistency( "sane_get_parameters" );
|
2010-06-04 17:54:51 +02:00
|
|
|
if (nStatus != SANE_STATUS_GOOD || aParams.bytes_per_line == 0)
|
|
|
|
{
|
2014-04-30 11:46:15 +02:00
|
|
|
bSuccess = false;
|
2010-06-04 17:54:51 +02:00
|
|
|
break;
|
|
|
|
}
|
2016-03-09 17:29:55 +05:30
|
|
|
#if (OSL_DEBUG_LEVEL > 0) || defined DBG_UTIL
|
2017-07-30 12:16:31 +02:00
|
|
|
const char* const ppFormats[] = { "SANE_FRAME_GRAY", "SANE_FRAME_RGB",
|
2000-09-18 15:18:56 +00:00
|
|
|
"SANE_FRAME_RED", "SANE_FRAME_GREEN",
|
|
|
|
"SANE_FRAME_BLUE", "Unknown !!!" };
|
|
|
|
fprintf( stderr, "Parameters for frame %d:\n", nStream );
|
2017-09-11 14:27:57 +02:00
|
|
|
if( static_cast<
|
|
|
|
typename std::make_unsigned<
|
|
|
|
typename std::underlying_type<SANE_Frame>::type>::type>(
|
|
|
|
aParams.format)
|
|
|
|
> 4 )
|
|
|
|
{
|
2018-01-15 09:05:45 +01:00
|
|
|
aParams.format = SANE_Frame(5);
|
2017-09-11 14:27:57 +02:00
|
|
|
}
|
2018-01-12 20:24:28 +01:00
|
|
|
fprintf( stderr, "format: %s\n", ppFormats[ static_cast<int>(aParams.format) ] );
|
2000-09-18 15:18:56 +00:00
|
|
|
fprintf( stderr, "last_frame: %s\n", aParams.last_frame ? "TRUE" : "FALSE" );
|
2018-01-12 20:24:28 +01:00
|
|
|
fprintf( stderr, "depth: %d\n", static_cast<int>(aParams.depth) );
|
|
|
|
fprintf( stderr, "pixels_per_line: %d\n", static_cast<int>(aParams.pixels_per_line) );
|
|
|
|
fprintf( stderr, "bytes_per_line: %d\n", static_cast<int>(aParams.bytes_per_line) );
|
2000-09-18 15:18:56 +00:00
|
|
|
#endif
|
|
|
|
if( ! pBuffer )
|
|
|
|
{
|
2018-10-23 08:23:32 +02:00
|
|
|
pBuffer.reset(new sal_uInt8[ BYTE_BUFFER_SIZE < 4*aParams.bytes_per_line ? 4*aParams.bytes_per_line : BYTE_BUFFER_SIZE ]);
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if( aParams.last_frame )
|
|
|
|
nStream=3;
|
|
|
|
|
|
|
|
switch( aParams.format )
|
|
|
|
{
|
|
|
|
case SANE_FRAME_GRAY:
|
|
|
|
eType = FrameStyle_Gray;
|
|
|
|
if( aParams.depth == 1 )
|
|
|
|
eType = FrameStyle_BW;
|
|
|
|
break;
|
|
|
|
case SANE_FRAME_RGB:
|
|
|
|
eType = FrameStyle_RGB;
|
|
|
|
break;
|
|
|
|
case SANE_FRAME_RED:
|
|
|
|
case SANE_FRAME_GREEN:
|
|
|
|
case SANE_FRAME_BLUE:
|
|
|
|
eType = FrameStyle_Separated;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fprintf( stderr, "Warning: unknown frame style !!!\n" );
|
|
|
|
}
|
|
|
|
|
2014-04-30 11:46:15 +02:00
|
|
|
bool bSynchronousRead = true;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
|
|
|
// should be fail safe, but ... ??
|
|
|
|
nStatus = p_set_io_mode( maHandle, SANE_FALSE );
|
|
|
|
CheckConsistency( "sane_set_io_mode" );
|
|
|
|
if( nStatus != SANE_STATUS_GOOD )
|
|
|
|
{
|
2014-04-30 11:46:15 +02:00
|
|
|
bSynchronousRead = false;
|
2017-07-24 09:39:37 +01:00
|
|
|
nStatus = p_set_io_mode(maHandle, SANE_TRUE);
|
2000-09-18 15:18:56 +00:00
|
|
|
CheckConsistency( "sane_set_io_mode" );
|
2017-07-24 09:39:37 +01:00
|
|
|
if (nStatus != SANE_STATUS_GOOD)
|
|
|
|
{
|
|
|
|
SAL_WARN("extensions.scanner", "SANE driver status is: " << nStatus);
|
|
|
|
}
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SANE_Int nLen=0;
|
|
|
|
SANE_Int fd = 0;
|
|
|
|
|
|
|
|
if( ! bSynchronousRead )
|
|
|
|
{
|
|
|
|
nStatus = p_get_select_fd( maHandle, &fd );
|
|
|
|
DUMP_STATE( nStatus, "sane_get_select_fd" );
|
|
|
|
CheckConsistency( "sane_get_select_fd" );
|
|
|
|
if( nStatus != SANE_STATUS_GOOD )
|
2014-04-30 11:46:15 +02:00
|
|
|
bSynchronousRead = true;
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
2014-11-14 11:06:44 +00:00
|
|
|
utl::TempFile aFrame;
|
|
|
|
aFrame.EnableKillingFile();
|
2015-01-27 10:22:30 +00:00
|
|
|
FILE* pFrame = fopen(OUStringToOString(aFrame.GetFileName(), osl_getThreadTextEncoding()).getStr(), "w+b");
|
2000-09-18 15:18:56 +00:00
|
|
|
if( ! pFrame )
|
|
|
|
{
|
2014-04-30 11:46:15 +02:00
|
|
|
bSuccess = false;
|
2000-09-18 15:18:56 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
do {
|
|
|
|
if( ! bSynchronousRead )
|
|
|
|
{
|
|
|
|
fd_set fdset;
|
|
|
|
struct timeval tv;
|
|
|
|
|
|
|
|
FD_ZERO( &fdset );
|
2018-01-12 20:24:28 +01:00
|
|
|
FD_SET( static_cast<int>(fd), &fdset );
|
2000-09-18 15:18:56 +00:00
|
|
|
tv.tv_sec = 5;
|
|
|
|
tv.tv_usec = 0;
|
2015-11-10 10:14:53 +01:00
|
|
|
if( select( fd+1, &fdset, nullptr, nullptr, &tv ) == 0 )
|
2018-01-25 12:25:21 +01:00
|
|
|
fprintf( stderr, "Timeout on sane_read descriptor\n" );
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
nLen = 0;
|
2018-10-23 08:23:32 +02:00
|
|
|
nStatus = p_read( maHandle, pBuffer.get(), BYTE_BUFFER_SIZE, &nLen );
|
2000-09-18 15:18:56 +00:00
|
|
|
CheckConsistency( "sane_read" );
|
|
|
|
if( nLen && ( nStatus == SANE_STATUS_GOOD ||
|
|
|
|
nStatus == SANE_STATUS_EOF ) )
|
|
|
|
{
|
2018-10-23 08:23:32 +02:00
|
|
|
bSuccess = (static_cast<size_t>(nLen) == fwrite( pBuffer.get(), 1, nLen, pFrame ));
|
2012-05-03 22:33:54 +01:00
|
|
|
if (!bSuccess)
|
|
|
|
break;
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
DUMP_STATE( nStatus, "sane_read" );
|
|
|
|
} while( nStatus == SANE_STATUS_GOOD );
|
2012-05-03 22:33:54 +01:00
|
|
|
if (nStatus != SANE_STATUS_EOF || !bSuccess)
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
|
|
|
fclose( pFrame );
|
2014-04-30 11:46:15 +02:00
|
|
|
bSuccess = false;
|
2000-09-18 15:18:56 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
int nFrameLength = ftell( pFrame );
|
|
|
|
fseek( pFrame, 0, SEEK_SET );
|
2018-01-12 20:24:28 +01:00
|
|
|
sal_uInt32 nWidth = static_cast<sal_uInt32>(aParams.pixels_per_line);
|
|
|
|
sal_uInt32 nHeight = static_cast<sal_uInt32>(nFrameLength / aParams.bytes_per_line);
|
2000-09-18 15:18:56 +00:00
|
|
|
if( ! bWidthSet )
|
|
|
|
{
|
2002-03-28 15:45:33 +00:00
|
|
|
if( ! fResl )
|
|
|
|
fResl = 300; // if all else fails that's a good guess
|
|
|
|
if( ! nWidthMM )
|
2018-01-12 20:24:28 +01:00
|
|
|
nWidthMM = static_cast<int>((static_cast<double>(nWidth) / fResl) * 25.4);
|
2002-03-28 15:45:33 +00:00
|
|
|
if( ! nHeightMM )
|
2018-01-12 20:24:28 +01:00
|
|
|
nHeightMM = static_cast<int>((static_cast<double>(nHeight) / fResl) * 25.4);
|
2016-03-09 17:29:55 +05:30
|
|
|
SAL_INFO("extensions.scanner", "set dimensions to(" << nWidth << ", " << nHeight << ") Pixel, (" << nWidthMM << ", " << nHeightMM <<
|
|
|
|
") mm, resolution is " << fResl);
|
2002-03-28 15:45:33 +00:00
|
|
|
|
2000-09-18 15:18:56 +00:00
|
|
|
aConverter.Seek( 18 );
|
2014-09-25 20:19:30 +02:00
|
|
|
aConverter.WriteUInt32( nWidth );
|
|
|
|
aConverter.WriteUInt32( nHeight );
|
2002-03-28 15:45:33 +00:00
|
|
|
aConverter.Seek( 38 );
|
2015-01-16 08:07:06 +02:00
|
|
|
aConverter.WriteUInt32( 1000*nWidth/nWidthMM );
|
|
|
|
aConverter.WriteUInt32( 1000*nHeight/nHeightMM );
|
2014-04-30 11:46:15 +02:00
|
|
|
bWidthSet = true;
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
aConverter.Seek(60);
|
|
|
|
|
|
|
|
if( eType == FrameStyle_BW )
|
|
|
|
{
|
|
|
|
aConverter.Seek( 10 );
|
2014-09-25 20:19:30 +02:00
|
|
|
aConverter.WriteUInt32( 64 );
|
2000-09-18 15:18:56 +00:00
|
|
|
aConverter.Seek( 28 );
|
2014-09-25 17:56:24 +02:00
|
|
|
aConverter.WriteUInt16( 1 );
|
2000-09-18 15:18:56 +00:00
|
|
|
aConverter.Seek( 54 );
|
|
|
|
// write color table
|
2014-09-25 17:56:24 +02:00
|
|
|
aConverter.WriteUInt16( 0xffff );
|
2014-09-25 06:07:13 +02:00
|
|
|
aConverter.WriteUChar( 0xff );
|
|
|
|
aConverter.WriteUChar( 0 );
|
2014-09-25 20:19:30 +02:00
|
|
|
aConverter.WriteUInt32( 0 );
|
2000-09-18 15:18:56 +00:00
|
|
|
aConverter.Seek( 64 );
|
|
|
|
}
|
|
|
|
else if( eType == FrameStyle_Gray )
|
|
|
|
{
|
2019-02-08 13:15:15 +02:00
|
|
|
aConverter.Seek( 10 );
|
|
|
|
aConverter.WriteUInt32( 1084 );
|
2000-09-18 15:18:56 +00:00
|
|
|
aConverter.Seek( 28 );
|
2014-09-25 17:56:24 +02:00
|
|
|
aConverter.WriteUInt16( 8 );
|
2000-09-18 15:18:56 +00:00
|
|
|
aConverter.Seek( 54 );
|
|
|
|
// write color table
|
|
|
|
for( nLine = 0; nLine < 256; nLine++ )
|
|
|
|
{
|
2014-09-25 06:07:13 +02:00
|
|
|
aConverter.WriteUChar( nLine );
|
|
|
|
aConverter.WriteUChar( nLine );
|
|
|
|
aConverter.WriteUChar( nLine );
|
|
|
|
aConverter.WriteUChar( 0 );
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
aConverter.Seek( 1084 );
|
|
|
|
}
|
|
|
|
|
2012-04-21 22:24:03 +01:00
|
|
|
for (nLine = nHeight-1; nLine >= 0; --nLine)
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
2018-11-04 15:59:19 +00:00
|
|
|
if (fseek(pFrame, nLine * aParams.bytes_per_line, SEEK_SET) == -1)
|
|
|
|
{
|
|
|
|
bSuccess = false;
|
|
|
|
break;
|
|
|
|
}
|
2000-09-18 15:18:56 +00:00
|
|
|
if( eType == FrameStyle_BW ||
|
|
|
|
( eType == FrameStyle_Gray && aParams.depth == 8 )
|
|
|
|
)
|
|
|
|
{
|
2018-10-23 08:23:32 +02:00
|
|
|
SANE_Int items_read = fread( pBuffer.get(), 1, aParams.bytes_per_line, pFrame );
|
2012-04-21 22:24:03 +01:00
|
|
|
if (items_read != aParams.bytes_per_line)
|
2012-04-21 14:29:14 +02:00
|
|
|
{
|
2012-04-21 22:24:03 +01:00
|
|
|
SAL_WARN( "extensions.scanner", "short read, padding with zeros" );
|
2018-10-23 08:23:32 +02:00
|
|
|
memset(pBuffer.get() + items_read, 0, aParams.bytes_per_line - items_read);
|
2012-04-21 14:29:14 +02:00
|
|
|
}
|
2018-10-23 08:23:32 +02:00
|
|
|
aConverter.WriteBytes(pBuffer.get(), aParams.bytes_per_line);
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
else if( eType == FrameStyle_Gray )
|
|
|
|
{
|
|
|
|
for( i = 0; i < (aParams.pixels_per_line); i++ )
|
|
|
|
{
|
2016-04-13 23:12:36 +02:00
|
|
|
sal_uInt8 nGray = ReadValue( pFrame, aParams.depth );
|
2014-01-08 08:48:26 +02:00
|
|
|
aConverter.WriteUChar( nGray );
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( eType == FrameStyle_RGB )
|
|
|
|
{
|
|
|
|
for( i = 0; i < (aParams.pixels_per_line); i++ )
|
|
|
|
{
|
2011-01-14 12:13:45 +01:00
|
|
|
sal_uInt8 nRed, nGreen, nBlue;
|
2016-04-13 23:12:36 +02:00
|
|
|
nRed = ReadValue( pFrame, aParams.depth );
|
|
|
|
nGreen = ReadValue( pFrame, aParams.depth );
|
|
|
|
nBlue = ReadValue( pFrame, aParams.depth );
|
2014-01-08 08:48:26 +02:00
|
|
|
aConverter.WriteUChar( nBlue );
|
|
|
|
aConverter.WriteUChar( nGreen );
|
|
|
|
aConverter.WriteUChar( nRed );
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( eType == FrameStyle_Separated )
|
|
|
|
{
|
|
|
|
for( i = 0; i < (aParams.pixels_per_line); i++ )
|
|
|
|
{
|
2016-04-13 23:12:36 +02:00
|
|
|
sal_uInt8 nValue = ReadValue( pFrame, aParams.depth );
|
2000-09-18 15:18:56 +00:00
|
|
|
switch( aParams.format )
|
|
|
|
{
|
|
|
|
case SANE_FRAME_RED:
|
|
|
|
aConverter.SeekRel( 2 );
|
2014-01-08 08:48:26 +02:00
|
|
|
aConverter.WriteUChar( nValue );
|
2000-09-18 15:18:56 +00:00
|
|
|
break;
|
|
|
|
case SANE_FRAME_GREEN:
|
|
|
|
aConverter.SeekRel( 1 );
|
2014-01-08 08:48:26 +02:00
|
|
|
aConverter.WriteUChar( nValue );
|
2000-09-18 15:18:56 +00:00
|
|
|
aConverter.SeekRel( 1 );
|
|
|
|
break;
|
|
|
|
case SANE_FRAME_BLUE:
|
2014-01-08 08:48:26 +02:00
|
|
|
aConverter.WriteUChar( nValue );
|
2000-09-18 15:18:56 +00:00
|
|
|
aConverter.SeekRel( 2 );
|
|
|
|
break;
|
2008-01-14 14:03:00 +00:00
|
|
|
case SANE_FRAME_GRAY:
|
|
|
|
case SANE_FRAME_RGB:
|
|
|
|
break;
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-11-04 15:56:17 +00:00
|
|
|
int nGap = aConverter.Tell() & 3;
|
|
|
|
if (nGap)
|
|
|
|
aConverter.SeekRel( 4-nGap );
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
fclose( pFrame ); // deletes tmpfile
|
|
|
|
if( eType != FrameStyle_Separated )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
2014-04-30 11:46:15 +02:00
|
|
|
bSuccess = false;
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
// get stream length
|
2018-10-11 18:49:34 +02:00
|
|
|
int nPos = aConverter.TellEnd();
|
2000-09-18 15:18:56 +00:00
|
|
|
|
|
|
|
aConverter.Seek( 2 );
|
2014-09-25 20:19:30 +02:00
|
|
|
aConverter.WriteUInt32( nPos+1 );
|
2000-09-18 15:18:56 +00:00
|
|
|
aConverter.Seek( 0 );
|
|
|
|
|
|
|
|
rBitmap.unlock();
|
|
|
|
|
|
|
|
if( bSuccess )
|
|
|
|
{
|
|
|
|
// only cancel a successful operation
|
|
|
|
// sane disrupts memory else
|
|
|
|
p_cancel( maHandle );
|
|
|
|
CheckConsistency( "sane_cancel" );
|
|
|
|
}
|
2018-10-23 08:23:32 +02:00
|
|
|
pBuffer.reset();
|
2000-09-18 15:18:56 +00:00
|
|
|
|
|
|
|
ReloadOptions();
|
|
|
|
|
|
|
|
|
|
|
|
dbg_msg( "Sane::Start returns with %s\n", bSuccess ? "TRUE" : "FALSE" );
|
|
|
|
|
|
|
|
return bSuccess;
|
|
|
|
}
|
|
|
|
|
2018-05-08 10:29:21 +02:00
|
|
|
int Sane::GetRange( int n, std::unique_ptr<double[]>& rpDouble )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
|
|
|
if( mppOptions[n]->constraint_type != SANE_CONSTRAINT_RANGE &&
|
|
|
|
mppOptions[n]->constraint_type != SANE_CONSTRAINT_WORD_LIST )
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-11-10 10:14:53 +01:00
|
|
|
rpDouble = nullptr;
|
2000-09-18 15:18:56 +00:00
|
|
|
int nItems, i;
|
2015-04-24 12:25:53 +02:00
|
|
|
bool bIsFixed = mppOptions[n]->type == SANE_TYPE_FIXED;
|
2000-09-18 15:18:56 +00:00
|
|
|
|
|
|
|
dbg_msg( "Sane::GetRange of option %s ", mppOptions[n]->name );
|
|
|
|
if(mppOptions[n]->constraint_type == SANE_CONSTRAINT_RANGE )
|
|
|
|
{
|
|
|
|
double fMin, fMax, fQuant;
|
|
|
|
if( bIsFixed )
|
|
|
|
{
|
|
|
|
fMin = SANE_UNFIX( mppOptions[n]->constraint.range->min );
|
|
|
|
fMax = SANE_UNFIX( mppOptions[n]->constraint.range->max );
|
|
|
|
fQuant = SANE_UNFIX( mppOptions[n]->constraint.range->quant );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-01-12 20:24:28 +01:00
|
|
|
fMin = static_cast<double>(mppOptions[n]->constraint.range->min);
|
|
|
|
fMax = static_cast<double>(mppOptions[n]->constraint.range->max);
|
|
|
|
fQuant = static_cast<double>(mppOptions[n]->constraint.range->quant);
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
|
|
|
if( fQuant != 0.0 )
|
|
|
|
{
|
|
|
|
dbg_msg( "quantum range [ %lg ; %lg ; %lg ]\n",
|
|
|
|
fMin, fQuant, fMax );
|
2018-01-12 20:24:28 +01:00
|
|
|
nItems = static_cast<int>((fMax - fMin)/fQuant)+1;
|
2018-05-08 10:29:21 +02:00
|
|
|
rpDouble.reset(new double[ nItems ]);
|
2000-09-18 15:18:56 +00:00
|
|
|
double fValue = fMin;
|
|
|
|
for( i = 0; i < nItems; i++, fValue += fQuant )
|
|
|
|
rpDouble[i] = fValue;
|
|
|
|
rpDouble[ nItems-1 ] = fMax;
|
|
|
|
return nItems;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dbg_msg( "normal range [ %lg %lg ]\n",
|
|
|
|
fMin, fMax );
|
2018-05-08 10:29:21 +02:00
|
|
|
rpDouble.reset(new double[2]);
|
2000-09-18 15:18:56 +00:00
|
|
|
rpDouble[0] = fMin;
|
|
|
|
rpDouble[1] = fMax;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nItems = mppOptions[n]->constraint.word_list[0];
|
2018-05-08 10:29:21 +02:00
|
|
|
rpDouble.reset(new double[nItems]);
|
2000-09-18 15:18:56 +00:00
|
|
|
for( i=0; i<nItems; i++ )
|
|
|
|
{
|
|
|
|
rpDouble[i] = bIsFixed ?
|
|
|
|
SANE_UNFIX( mppOptions[n]->constraint.word_list[i+1] ) :
|
2018-01-12 20:24:28 +01:00
|
|
|
static_cast<double>(mppOptions[n]->constraint.word_list[i+1]);
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
2003-04-17 14:14:24 +00:00
|
|
|
dbg_msg( "wordlist [ %lg ... %lg ]\n",
|
2000-09-18 15:18:56 +00:00
|
|
|
rpDouble[ 0 ], rpDouble[ nItems-1 ] );
|
|
|
|
return nItems;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-14 14:03:00 +00:00
|
|
|
static const char *ppUnits[] = {
|
2000-09-18 15:18:56 +00:00
|
|
|
"",
|
|
|
|
"[Pixel]",
|
|
|
|
"[Bit]",
|
|
|
|
"[mm]",
|
|
|
|
"[DPI]",
|
|
|
|
"[%]",
|
|
|
|
"[usec]"
|
|
|
|
};
|
|
|
|
|
2013-09-19 15:20:39 +02:00
|
|
|
OUString Sane::GetOptionUnitName( int n )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
2013-09-19 15:20:39 +02:00
|
|
|
OUString aText;
|
2000-09-18 15:18:56 +00:00
|
|
|
SANE_Unit nUnit = mppOptions[n]->unit;
|
2018-01-12 20:24:28 +01:00
|
|
|
size_t nUnitAsSize = static_cast<size_t>(nUnit);
|
2012-07-27 17:31:08 +02:00
|
|
|
if (nUnitAsSize >= SAL_N_ELEMENTS( ppUnits ))
|
2013-09-19 15:20:39 +02:00
|
|
|
aText = "[unknown units]";
|
2000-09-18 15:18:56 +00:00
|
|
|
else
|
2013-09-19 15:20:39 +02:00
|
|
|
aText = OUString( ppUnits[ nUnit ], strlen(ppUnits[ nUnit ]), osl_getThreadTextEncoding() );
|
2000-09-18 15:18:56 +00:00
|
|
|
return aText;
|
|
|
|
}
|
|
|
|
|
2014-04-30 11:46:15 +02:00
|
|
|
bool Sane::ActivateButtonOption( int n )
|
2000-09-18 15:18:56 +00:00
|
|
|
{
|
2015-11-10 10:14:53 +01:00
|
|
|
SANE_Status nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, nullptr );
|
2018-10-18 08:27:05 +02:00
|
|
|
return nStatus == SANE_STATUS_GOOD;
|
2000-09-18 15:18:56 +00:00
|
|
|
}
|
2010-10-12 15:57:08 +02:00
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|