code_device/hgsane/sane_option.cpp

418 lines
11 KiB
C++

#include "sane_option.h"
#include <sane/sane_option_definitions.h>
#include "../sdk/hginclude/huagaoxxx_warraper_ex.h"
#include "../sdk/hginclude/utils.h"
#include "../sdk/json/gb_json.h"
#include "../../sdk/include/lang/app_language.h"
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
static struct _paper_size
{
const char* title;
int width;
int height;
}g_paper[] =
{
{OPTION_VALUE_ZZCC_A3, 297, 420},
{OPTION_VALUE_ZZCC_8K, 297, 420},
{OPTION_VALUE_ZZCC_A4HX,297, 210},
{OPTION_VALUE_ZZCC_B4, 257, 364},
{OPTION_VALUE_ZZCC_B5HX,250, 176}, // {PAPER_B5, {182, 257}},
{OPTION_VALUE_ZZCC_A4, 210, 297},
{OPTION_VALUE_ZZCC_16K, 210, 285}, // {PAPER_16K, {185, 260}}
{OPTION_VALUE_ZZCC_A5HX,210, 148},
{OPTION_VALUE_ZZCC_B5, 176, 250}, // {PAPER_B5, {182, 257}},
{OPTION_VALUE_ZZCC_B6HX,176, 125},
{OPTION_VALUE_ZZCC_A5, 148, 210},
{OPTION_VALUE_ZZCC_A6HX,148, 105},
{OPTION_VALUE_ZZCC_B6, 125, 176},
{OPTION_VALUE_ZZCC_A6, 105, 148}
};
static void match_paper(char* buf, int cx, int cy)
{
unsigned long fc0 = -1, fc1 = 0;
int index = -1;
fc0 = 1600 + 40000;
for (size_t i = 0; i < ARRAY_SIZE(g_paper); ++i)
{
fc1 = (cx - g_paper[i].width) * (cx - g_paper[i].width);
fc1 += (cy - g_paper[i].height) * (cy - g_paper[i].height);
if (fc1 < fc0)
{
fc0 = fc1;
index = i;
}
}
if (index == -1)
strcpy(buf, from_default_language(OPTION_VALUE_ZZCC_PPYSCC, NULL));
else
strcpy(buf, from_default_language(g_paper[index].title, NULL));
utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "match paper(%u * %u) to '%s'\n", cx, cy, (char*)buf);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// sane_std_opts
sane_std_opts::sane_std_opts(int opt_base) : opt_num_base_(opt_base), page_height_(0), page_width_(0)
{}
sane_std_opts::~sane_std_opts()
{
for (size_t i = 0; i < known_opts_.size(); ++i)
{
char* buf = (char*)known_opts_[i].known.desc;
delete[] buf;
}
known_opts_.clear();
}
SANE_Option_Descriptor* sane_std_opts::get_known_option(int opt, int* ind)
{
if (ind)
*ind = -1;
for (size_t i = 0; i < known_opts_.size(); ++i)
{
if (known_opts_[i].known.opt == opt)
{
if (ind)
*ind = i;
return known_opts_[i].known.desc;
}
}
return nullptr;
}
SANE_Option_Descriptor* sane_std_opts::get_known_option(const char* name, int* ind)
{
if (ind)
*ind = -1;
for (size_t i = 0; i < known_opts_.size(); ++i)
{
if (strcmp(known_opts_[i].known.desc->name, name) == 0)
{
if (ind)
*ind = i;
return known_opts_[i].known.desc;
}
}
return nullptr;
}
void sane_std_opts::to_known_opt_value(OPTMAP* opmap, const void* data, void* known_data)
{
if (strcmp(opmap->known.desc->name, SANE_STD_OPT_NAME_DUPLEX) == 0)
{
*((SANE_Bool*)known_data) = strcmp((char*)data, from_default_language(OPTION_VALUE_SMYM_DM, NULL)) == 0 ? SANE_FALSE : SANE_TRUE;
}
else if (strcmp(opmap->user.desc->name, SANE_STD_OPT_NAME_PAGE) == 0)
{
bool ok = false;
for (size_t i = 0; i < ARRAY_SIZE(g_paper); ++i)
{
if (strcmp((char*)data, g_paper[i].title) == 0)
{
page_width_ = g_paper[i].width;
page_height_ = g_paper[i].height;
ok = true;
break;
}
}
if (!ok)
{
page_width_ = 2338;
page_height_ = 3307;
}
if (strcmp(opmap->known.desc->name, SANE_STD_OPT_NAME_PAPER_W) == 0)
*((SANE_Int*)known_data) = page_width_;
else if (strcmp(opmap->known.desc->name, SANE_STD_OPT_NAME_PAPER_H) == 0)
*((SANE_Int*)known_data) = page_height_;
}
}
void* sane_std_opts::from_known_opt_value(OPTMAP* opmap, const void* known_data, long* len)
{
void* buf = nullptr;
int size = opmap->user.desc->size;
if (strcmp(opmap->known.desc->name, SANE_STD_OPT_NAME_DUPLEX) == 0)
{
buf = local_utility::acquire_memory(size + 4, "");
memset(buf, 0, size + 4);
if (len)
*len = size;
if (*((const SANE_Bool*)known_data) == SANE_TRUE)
strcpy((char*)buf, from_default_language(OPTION_VALUE_SMYM_SM, NULL));
else
strcpy((char*)buf, from_default_language(OPTION_VALUE_SMYM_DM, NULL));
}
else if (strcmp(opmap->user.desc->name, SANE_STD_OPT_NAME_PAPER) == 0)
{
int cx = page_width_,
cy = page_height_;
buf = local_utility::acquire_memory(size + 4, "");
memset(buf, 0, size + 4);
if (len)
*len = size;
if (strcmp(opmap->known.desc->name, SANE_STD_OPT_NAME_PAPER_W) == 0)
page_width_ = cx = *((SANE_Int*)known_data);
else
page_height_ = cy = *((SANE_Int*)known_data);
match_paper((char*)buf, cx, cy);
}
return buf;
}
gb_json* sane_std_opts::get_opt_json(scanner_handle h, int opt)
{
char* buf = nullptr;
long len = 0;
gb_json* jsn = nullptr;
if (hg_scanner_get_option(h, (const char*)opt, buf, &len) == SCANNER_ERR_INSUFFICIENT_MEMORY)
{
buf = new char[len + 8];
memset(buf, 0, len + 8);
if (hg_scanner_get_option(h, (const char*)opt, buf, &len) == SCANNER_ERR_OK)
{
jsn = new gb_json();
if (!jsn->attach_text(buf))
{
jsn->release();
jsn = nullptr;
}
}
delete[] buf;
}
return jsn;
}
void* sane_std_opts::get_current_value(scanner_handle h, int opt)
{
gb_json* jsn = sane_std_opts::get_opt_json(h, opt);
void* ret = nullptr;
if (jsn)
{
std::string val("");
int size = 0;
jsn->get_value("type", val);
jsn->get_value("size", size);
if (val == "string")
{
jsn->get_value("cur", val);
if (size < (int)val.length())
size = val.length() + 4;
ret = local_utility::acquire_memory(size, "");
strcpy((char*)ret, val.c_str());
}
else if (val == "bool")
{
bool v = false;
jsn->get_value("cur", v);
ret = local_utility::acquire_memory(sizeof(SANE_Bool), "");
*((SANE_Bool*)ret) = v ? SANE_TRUE : SANE_FALSE;
}
else if (val == "int")
{
int v = 0;
jsn->get_value("cur", v);
ret = local_utility::acquire_memory(sizeof(SANE_Int), "");
*((SANE_Int*)ret) = v;
}
else if (val == "float")
{
double v = .0f;
jsn->get_value("cur", v);
ret = local_utility::acquire_memory(sizeof(SANE_Fixed), "");
*((SANE_Fixed*)ret) = SANE_FIX(v);
}
jsn->release();
}
return ret;
}
void sane_std_opts::init_known_opt(int option, SANE_Option_Descriptor* desc)
{
if (strcmp(desc->name, SANE_STD_OPT_NAME_PAGE) == 0)
{
// duplex
if (!get_known_option(SANE_STD_OPT_NAME_DUPLEX))
{
OPTMAP om;
int size = sizeof(SANE_Option_Descriptor);
om.user.opt = option;
om.user.desc = desc;
om.known.opt = opt_num_base_ + known_opts_.size();
om.known.desc = (SANE_Option_Descriptor*)new char[size];
memset(om.known.desc, 0, size);
om.known.desc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
om.known.desc->constraint_type = SANE_CONSTRAINT_NONE;
om.known.desc->desc = "set page to be simplex or duplex";
om.known.desc->name = SANE_STD_OPT_NAME_DUPLEX;
om.known.desc->size = sizeof(SANE_Bool);
om.known.desc->title = "Duplex";
om.known.desc->type = SANE_TYPE_BOOL;
om.known.desc->unit = SANE_UNIT_NONE;
om.init = "true";
known_opts_.push_back(om);
}
}
else if (strcmp(desc->name, SANE_STD_OPT_NAME_PAPER) == 0)
{
// page-width && page-height
if (!get_known_option(SANE_STD_OPT_NAME_PAPER_W))
{
OPTMAP om;
int size = sizeof(SANE_Option_Descriptor);
om.user.opt = option;
om.user.desc = desc;
om.known.opt = opt_num_base_ + known_opts_.size();
om.known.desc = (SANE_Option_Descriptor*)new char[size];
memset(om.known.desc, 0, size);
om.known.desc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
om.known.desc->constraint_type = SANE_CONSTRAINT_NONE;
om.known.desc->desc = "set page width";
om.known.desc->name = SANE_STD_OPT_NAME_PAPER_W;
om.known.desc->size = sizeof(SANE_Int);
om.known.desc->title = "Page Width";
om.known.desc->type = SANE_TYPE_INT;
om.known.desc->unit = SANE_UNIT_MM;
om.init = "210";
known_opts_.push_back(om);
om.known.opt = opt_num_base_ + known_opts_.size();
om.known.desc = (SANE_Option_Descriptor*)new char[size];
memset(om.known.desc, 0, size);
om.known.desc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
om.known.desc->constraint_type = SANE_CONSTRAINT_NONE;
om.known.desc->desc = "set page height";
om.known.desc->name = SANE_STD_OPT_NAME_PAPER_H;
om.known.desc->size = sizeof(SANE_Int);
om.known.desc->title = "Page Height";
om.known.desc->type = SANE_TYPE_INT;
om.known.desc->unit = SANE_UNIT_MM;
om.init = "297";
known_opts_.push_back(om);
}
}
}
SANE_Option_Descriptor* sane_std_opts::get_option(int option)
{
return get_known_option(option);
}
void sane_std_opts::clear(void)
{
for (auto& v : known_opts_)
{
delete[] v.known.desc;
}
known_opts_.clear();
}
bool sane_std_opts::is_known_option(int opt, SANE_Option_Descriptor** user)
{
int ind = -1;
SANE_Option_Descriptor* sod = get_known_option(opt, &ind);
if (user && ind != -1)
*user = known_opts_[ind].user.desc;
return sod != nullptr;
}
void* sane_std_opts::get_default_value(scanner_handle h, int opt)
{
int ind = -1;
void* ret = nullptr;
if (get_known_option(opt, &ind))
{
OPTMAP* op = &known_opts_[ind];
if (op->known.desc->type == SANE_TYPE_BOOL)
{
ret = local_utility::acquire_memory(sizeof(SANE_Bool), nullptr);
*(SANE_Bool*)ret = op->init == "true" ? SANE_TRUE : SANE_FALSE;
}
else if (op->known.desc->type == SANE_TYPE_INT)
{
ret = local_utility::acquire_memory(sizeof(SANE_Int), nullptr);
*(SANE_Int*)ret = atoi(op->init.c_str());
}
else if(op->known.desc->type == SANE_TYPE_FIXED)
{
ret = local_utility::acquire_memory(sizeof(SANE_Fixed), nullptr);
*(SANE_Fixed*)ret = SANE_FIX(atof(op->init.c_str()));
}
else if (op->known.desc->type == SANE_TYPE_STRING)
{
ret = local_utility::acquire_memory(op->known.desc->size + 4, nullptr);
memset(ret, 0, op->known.desc->size + 4);
strcpy((char*)ret, op->init.c_str());
}
}
return ret;
}
scanner_err sane_std_opts::get_value(scanner_handle h, int opt, void* buf)
{
int ind = -1;
scanner_err statu = SCANNER_ERR_INVALID_PARAMETER;
if (get_known_option(opt, &ind))
{
OPTMAP* op = &known_opts_[ind];
void* data = sane_std_opts::get_current_value(h, op->user.opt);
if (data)
{
to_known_opt_value(op, data, buf);
local_utility::free_memory(data);
}
}
return statu;
}
scanner_err sane_std_opts::set_value(scanner_handle h, int opt, void* buf)
{
int ind = -1;
scanner_err statu = SCANNER_ERR_INVALID_PARAMETER;
if (get_known_option(opt, &ind))
{
OPTMAP* op = &known_opts_[ind];
long len = 0;
void* data = from_known_opt_value(op, buf, &len);
utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "%d->%d: %s\n", opt, op->user.opt, (char*)data);
statu = hg_scanner_set_option(h, (const char*)op->user.opt, data, &len);
if (statu == SCANNER_ERR_NOT_EXACT)
to_known_opt_value(op, data, buf);
if (data)
local_utility::free_memory(data);
}
return statu;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////