#include "sane_option.h" #include #include "../sdk/hginclude/huagaoxxx_warraper_ex.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)); VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "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; } json* sane_std_opts::get_opt_json(scanner_handle h, int opt) { char* buf = nullptr; long len = 0; json* jsn = nullptr; if (hg_scanner_get_parameter(h, (const char*)opt, buf, &len) == SCANNER_ERR_INSUFFICIENT_MEMORY) { buf = new char[len + 8]; memset(buf, 0, len + 8); if (hg_scanner_get_parameter(h, (const char*)opt, buf, &len) == SCANNER_ERR_OK) { jsn = new json(); if (!jsn->attach_text(buf)) { delete jsn; jsn = nullptr; } } delete[] buf; } return jsn; } void* sane_std_opts::get_current_value(scanner_handle h, int opt) { 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); } delete jsn; } 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); VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "%d->%d: %s\n", opt, op->user.opt, (char*)data); statu = hg_scanner_set_parameter(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; }