diff options
| author | Jörg Frings-Fürst <debian@jff.email> | 2023-02-16 10:20:08 +0100 | 
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff.email> | 2023-02-16 10:20:08 +0100 | 
| commit | 778ebf8ee9cb22ea5727844333bcd5a6ee6bc0de (patch) | |
| tree | a754e785b286ed82b45fe4e50b980714ad80e0a7 /backend/genesys/genesys.cpp | |
| parent | 7d8aac1f3634dc58785bec7acf097dd6bac8c394 (diff) | |
| parent | 32cb765f681299af226ca0520993cbe47ba5ecd0 (diff) | |
Merge branch 'release/debian/1.2.1-1'debian/1.2.1-1
Diffstat (limited to 'backend/genesys/genesys.cpp')
| -rw-r--r-- | backend/genesys/genesys.cpp | 226 | 
1 files changed, 137 insertions, 89 deletions
| diff --git a/backend/genesys/genesys.cpp b/backend/genesys/genesys.cpp index 5aba58c..ab1367e 100644 --- a/backend/genesys/genesys.cpp +++ b/backend/genesys/genesys.cpp @@ -310,9 +310,8 @@ void sanei_genesys_init_structs (Genesys_Device * dev)   * @param gamma gamma to compute values   * @return a gamma table filled with the computed values   * */ -void -sanei_genesys_create_gamma_table (std::vector<uint16_t>& gamma_table, int size, -                                  float maximum, float gamma_max, float gamma) +void sanei_genesys_create_gamma_table(std::vector<std::uint16_t>& gamma_table, int size, +                                      float maximum, float gamma_max, float gamma)  {      gamma_table.clear();      gamma_table.resize(size, 0); @@ -334,7 +333,7 @@ sanei_genesys_create_gamma_table (std::vector<uint16_t>& gamma_table, int size,  }  void sanei_genesys_create_default_gamma_table(Genesys_Device* dev, -                                              std::vector<uint16_t>& gamma_table, float gamma) +                                              std::vector<std::uint16_t>& gamma_table, float gamma)  {      int size = 0;      int max = 0; @@ -346,6 +345,7 @@ void sanei_genesys_create_default_gamma_table(Genesys_Device* dev,          }          max = size - 1;      } else if (dev->model->asic_type == AsicType::GL124 || +               dev->model->asic_type == AsicType::GL845 ||                 dev->model->asic_type == AsicType::GL846 ||                 dev->model->asic_type == AsicType::GL847) {          size = 257; @@ -396,7 +396,7 @@ SANE_Int sanei_genesys_exposure_time2(Genesys_Device * dev, const MotorProfile&     The data needs to be of size "size", and in little endian byte order.   */  static void genesys_send_offset_and_shading(Genesys_Device* dev, const Genesys_Sensor& sensor, -                                            uint8_t* data, int size) +                                            std::uint8_t* data, int size)  {      DBG_HELPER_ARGS(dbg, "(size = %d)", size);    int start_address; @@ -427,10 +427,10 @@ void sanei_genesys_init_shading_data(Genesys_Device* dev, const Genesys_Sensor&      unsigned channels = dev->settings.get_channels(); -  // 16 bit black, 16 bit white -  std::vector<uint8_t> shading_data(pixels_per_line * 4 * channels, 0); +    // 16 bit black, 16 bit white +    std::vector<std::uint8_t> shading_data(pixels_per_line * 4 * channels, 0); -  uint8_t* shading_data_ptr = shading_data.data(); +    std::uint8_t* shading_data_ptr = shading_data.data();      for (unsigned i = 0; i < pixels_per_line * channels; i++) {        *shading_data_ptr++ = 0x00;	/* dark lo */ @@ -487,7 +487,7 @@ void scanner_clear_scan_and_feed_counts(Genesys_Device& dev)  }  void scanner_send_slope_table(Genesys_Device* dev, const Genesys_Sensor& sensor, unsigned table_nr, -                              const std::vector<uint16_t>& slope_table) +                              const std::vector<std::uint16_t>& slope_table)  {      DBG_HELPER_ARGS(dbg, "table_nr = %d, steps = %zu", table_nr, slope_table.size()); @@ -515,7 +515,7 @@ void scanner_send_slope_table(Genesys_Device* dev, const Genesys_Sensor& sensor,          throw SaneException("invalid table number %d", table_nr);      } -    std::vector<uint8_t> table; +    std::vector<std::uint8_t> table;      table.reserve(slope_table.size() * 2);      for (std::size_t i = 0; i < slope_table.size(); i++) {          table.push_back(slope_table[i] & 0xff); @@ -1868,7 +1868,7 @@ void scanner_coarse_gain_calibration(Genesys_Device& dev, const Genesys_Sensor&              dev.model->asic_type == AsicType::GL842 ||              dev.model->asic_type == AsicType::GL843)          { -            std::vector<uint16_t> values; +            std::vector<std::uint16_t> values;              // FIXME: start from the second line because the first line often has artifacts. Probably              // caused by unclean cleanup of previous scan              for (std::size_t x = pixels / 4; x < (pixels * 3 / 4); x++) { @@ -2178,12 +2178,12 @@ SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor  }  void sanei_genesys_calculate_zmod(bool two_table, -                                  uint32_t exposure_time, -                                  const std::vector<uint16_t>& slope_table, +                                  std::uint32_t exposure_time, +                                  const std::vector<std::uint16_t>& slope_table,                                    unsigned acceleration_steps,                                    unsigned move_steps,                                    unsigned buffer_acceleration_steps, -                                  uint32_t* out_z1, uint32_t* out_z2) +                                  std::uint32_t* out_z1, std::uint32_t* out_z2)  {      // acceleration total time      unsigned sum = std::accumulate(slope_table.begin(), slope_table.begin() + acceleration_steps, @@ -2233,7 +2233,7 @@ static void genesys_shading_calibration_impl(Genesys_Device* dev, const Genesys_      debug_dump(DBG_info, dev->calib_session);    size_t size; -  uint32_t pixels_per_line; +    std::uint32_t pixels_per_line;      if (dev->model->asic_type == AsicType::GL842 ||          dev->model->asic_type == AsicType::GL843 || @@ -2274,7 +2274,7 @@ static void genesys_shading_calibration_impl(Genesys_Device* dev, const Genesys_          size = channels * 2 * pixels_per_line * (dev->calib_session.params.lines + 1);      } -  std::vector<uint16_t> calibration_data(size / 2); +    std::vector<std::uint16_t> calibration_data(size / 2);      // turn off motor and lamp power for flatbed scanners, but not for sheetfed scanners      // because they have a calibration sheet with a sufficient black strip @@ -2353,8 +2353,8 @@ static void genesys_shading_calibration_impl(Genesys_Device* dev, const Genesys_  static void genesys_dark_shading_by_dummy_pixel(Genesys_Device* dev, const Genesys_Sensor& sensor)  {      DBG_HELPER(dbg); -  uint32_t pixels_per_line; -  uint32_t skip, xend; +    std::uint32_t pixels_per_line; +    std::uint32_t skip, xend;    int dummy1, dummy2, dummy3;	/* dummy black average per channel */      if (dev->model->asic_type == AsicType::GL842 || @@ -2578,11 +2578,9 @@ static void genesys_dark_white_shading_calibration(Genesys_Device* dev,          dev->interface->write_registers(local_reg);      } -  size_t size; -  uint32_t pixels_per_line; +    std::size_t size; +    std::uint32_t pixels_per_line;    unsigned int x; -  uint32_t dark, white, dark_sum, white_sum, dark_count, white_count, col, -    dif;      if (dev->model->asic_type == AsicType::GL842 ||          dev->model->asic_type == AsicType::GL843) @@ -2618,7 +2616,7 @@ static void genesys_dark_white_shading_calibration(Genesys_Device* dev,          size = channels * 2 * pixels_per_line * dev->calib_session.params.lines;      } -  std::vector<uint8_t> calibration_data(size); +    std::vector<std::uint8_t> calibration_data(size);      // turn on motor and lamp power      sanei_genesys_set_lamp_power(dev, sensor, local_reg, true); @@ -2656,19 +2654,17 @@ static void genesys_dark_white_shading_calibration(Genesys_Device* dev,      std::fill(dev->white_average_data.begin(),                dev->white_average_data.begin() + start_offset * channels, 0); -    uint16_t* average_white = dev->white_average_data.data() + -                              start_offset * channels; -    uint16_t* average_dark = dev->dark_average_data.data() + -                             start_offset * channels; +    std::uint16_t* average_white = dev->white_average_data.data() + start_offset * channels; +    std::uint16_t* average_dark = dev->dark_average_data.data() + start_offset * channels;    for (x = 0; x < pixels_per_line * channels; x++)      { -      dark = 0xffff; -      white = 0; +        std::uint32_t dark = 0xffff; +        std::uint32_t white = 0;              for (std::size_t y = 0; y < dev->calib_session.params.lines; y++)  	{ -	  col = calibration_data[(x + y * pixels_per_line * channels) * 2]; +            std::uint32_t col = calibration_data[(x + y * pixels_per_line * channels) * 2];  	  col |=  	    calibration_data[(x + y * pixels_per_line * channels) * 2 +  			     1] << 8; @@ -2679,20 +2675,20 @@ static void genesys_dark_white_shading_calibration(Genesys_Device* dev,  	    dark = col;  	} -      dif = white - dark; +        std::uint32_t dif = white - dark;        dark = dark + dif / 8;        white = white - dif / 8; -      dark_count = 0; -      dark_sum = 0; +        std::uint32_t dark_count = 0; +        std::uint32_t dark_sum = 0; -      white_count = 0; -      white_sum = 0; +        std::uint32_t white_count = 0; +        std::uint32_t white_sum = 0;              for (std::size_t y = 0; y < dev->calib_session.params.lines; y++)  	{ -	  col = calibration_data[(x + y * pixels_per_line * channels) * 2]; +            std::uint32_t col = calibration_data[(x + y * pixels_per_line * channels) * 2];  	  col |=  	    calibration_data[(x + y * pixels_per_line * channels) * 2 +  			     1] << 8; @@ -2780,9 +2776,8 @@ compute_coefficient (unsigned int coeff, unsigned int target, unsigned int value   * @param target_bright value of the white target code   * @param target_dark value of the black target code  */ -static void -compute_averaged_planar (Genesys_Device * dev, const Genesys_Sensor& sensor, -			 uint8_t * shading_data, +static void compute_averaged_planar(Genesys_Device * dev, const Genesys_Sensor& sensor, +                                    std::uint8_t* shading_data,  			 unsigned int pixels_per_line,  			 unsigned int words_per_color,  			 unsigned int channels, @@ -2852,7 +2847,8 @@ compute_averaged_planar (Genesys_Device * dev, const Genesys_Sensor& sensor,      avgpixels = 15;    /* LiDE80 packs shading data */ -    if (dev->model->sensor_id != SensorId::CIS_CANON_LIDE_80) { +  if (dev->model->sensor_id != SensorId::CIS_CANON_LIDE_80) +    {        factor=1;        fill=avgpixels;      } @@ -2961,7 +2957,7 @@ static std::array<unsigned, 3> color_order_to_cmat(ColorOrder color_order)   * @param target value of the target code   */  static void compute_coefficients(Genesys_Device * dev, -		      uint8_t * shading_data, +                                 std::uint8_t* shading_data,  		      unsigned int pixels_per_line,  		      unsigned int channels,                                   ColorOrder color_order, @@ -2969,7 +2965,6 @@ static void compute_coefficients(Genesys_Device * dev,  		      unsigned int coeff,  		      unsigned int target)  { -  uint8_t *ptr;			/* contain 16bit words in little endian */    unsigned int x, c;    unsigned int val, br, dk;    unsigned int start, end; @@ -2995,7 +2990,8 @@ static void compute_coefficients(Genesys_Device * dev,        for (x = start; x < end; x++)  	{  	  /* TODO if channels=1 , use filter to know the base addr */ -	  ptr = shading_data + 4 * ((x + offset) * channels + cmat[c]); +            // contain 16bit words in little endian +            std::uint8_t* ptr = shading_data + 4 * ((x + offset) * channels + cmat[c]);          // dark data          dk = dev->dark_average_data[x * channels + c]; @@ -3033,7 +3029,7 @@ static void compute_coefficients(Genesys_Device * dev,   * @param target white target value   */  static void compute_planar_coefficients(Genesys_Device * dev, -			     uint8_t * shading_data, +                                        std::uint8_t* shading_data,  			     unsigned int factor,  			     unsigned int pixels_per_line,  			     unsigned int words_per_color, @@ -3043,22 +3039,20 @@ static void compute_planar_coefficients(Genesys_Device * dev,  			     unsigned int coeff,  			     unsigned int target)  { -  uint8_t *ptr;			/* contains 16bit words in little endian */ -  uint32_t x, c, i; -  uint32_t val, dk, br; +    std::uint32_t i; +    std::uint32_t val, dk, br;      auto cmat = color_order_to_cmat(color_order);    DBG(DBG_io, "%s: factor=%d, pixels_per_line=%d, words=0x%X, coeff=0x%04x\n", __func__, factor,        pixels_per_line, words_per_color, coeff); -  for (c = 0; c < channels; c++) -    { +    for (unsigned c = 0; c < channels; c++) {        /* shading data is larger than pixels_per_line so offset can be neglected */ -      for (x = 0; x < pixels_per_line; x+=factor) -	{ +        for (unsigned x = 0; x < pixels_per_line; x += factor) {  	  /* x2 because of 16 bit values, and x2 since one coeff for dark  	   * and another for white */ -	  ptr = shading_data + words_per_color * cmat[c] * 2 + (x + offset) * 4; +            // contains 16bit words in little endian +            std::uint8_t* ptr = shading_data + words_per_color * cmat[c] * 2 + (x + offset) * 4;  	  dk = 0;  	  br = 0; @@ -3074,9 +3068,8 @@ static void compute_planar_coefficients(Genesys_Device * dev,  	  val = compute_coefficient (coeff, target, br - dk); -	  /* we duplicate the information to have calibration data at optical resolution */ -	  for (i = 0; i < factor; i++) -	    { +            // we duplicate the information to have calibration data at optical resolution +            for (unsigned i = 0; i < factor; i++) {  	      ptr[0 + 4 * i] = dk & 255;  	      ptr[1 + 4 * i] = dk / 256;  	      ptr[2 + 4 * i] = val & 0xff; @@ -3097,10 +3090,9 @@ static void compute_planar_coefficients(Genesys_Device * dev,    }  } -static void -compute_shifted_coefficients (Genesys_Device * dev, -                              const Genesys_Sensor& sensor, -			      uint8_t * shading_data, +static void compute_shifted_coefficients(Genesys_Device * dev, +                                         const Genesys_Sensor& sensor, +                                         std::uint8_t* shading_data,  			      unsigned int pixels_per_line,  			      unsigned int channels,                                ColorOrder color_order, @@ -3112,7 +3104,7 @@ compute_shifted_coefficients (Genesys_Device * dev,  {    unsigned int x, avgpixels, basepixels, i, j, val1, val2;    unsigned int br_tmp [3], dk_tmp [3]; -  uint8_t *ptr = shading_data + offset * 3 * 4;                 /* contain 16bit words in little endian */ +    std::uint8_t* ptr = shading_data + offset * 3 * 4; // contain 16bit words in little endian    unsigned int patch_cnt = offset * 3;                          /* at start, offset of first patch */      auto cmat = color_order_to_cmat(color_order); @@ -3198,7 +3190,7 @@ static void genesys_send_shading_coefficient(Genesys_Device* dev, const Genesys_          return;      } -  uint32_t pixels_per_line; +    std::uint32_t pixels_per_line;    int o;    unsigned int length;		/**> number of shading calibration data words */    unsigned int factor; @@ -3255,8 +3247,8 @@ static void genesys_send_shading_coefficient(Genesys_Device* dev, const Genesys_    length = words_per_color * 3 * 2;    /* allocate computed size */ -  // contains 16bit words in little endian -  std::vector<uint8_t> shading_data(length, 0); +    // contains 16bit words in little endian +    std::vector<std::uint8_t> shading_data(length, 0);      if (!dev->calib_session.computed) {          genesys_send_offset_and_shading(dev, sensor, shading_data.data(), length); @@ -3584,7 +3576,7 @@ static void genesys_save_calibration(Genesys_Device* dev, const Genesys_Sensor&  static void genesys_flatbed_calibration(Genesys_Device* dev, Genesys_Sensor& sensor)  {      DBG_HELPER(dbg); -    uint32_t pixels_per_line; +    std::uint32_t pixels_per_line;      unsigned coarse_res = sensor.full_resolution;      if (dev->settings.yres <= sensor.full_resolution / 2) { @@ -3857,8 +3849,8 @@ static void genesys_warmup_lamp(Genesys_Device* dev)      auto channels = dev->session.params.channels;      auto lines = dev->session.output_line_count; -  std::vector<uint8_t> first_line(total_size); -  std::vector<uint8_t> second_line(total_size); +    std::vector<std::uint8_t> first_line(total_size); +    std::vector<std::uint8_t> second_line(total_size);      do {          first_line = second_line; @@ -4892,28 +4884,76 @@ static void init_options(Genesys_Scanner* s)      s->opt[OPT_POWER_SW].cap = SANE_CAP_INACTIVE;    /* extra button */ -    s->opt[OPT_EXTRA_SW].name = "extra"; -    s->opt[OPT_EXTRA_SW].title = SANE_I18N("Extra button"); -    s->opt[OPT_EXTRA_SW].desc = SANE_I18N("Extra button"); -    s->opt[OPT_EXTRA_SW].type = SANE_TYPE_BOOL; -    s->opt[OPT_EXTRA_SW].unit = SANE_UNIT_NONE; -    if (model->buttons & GENESYS_HAS_EXTRA_SW) { -        s->opt[OPT_EXTRA_SW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; -    } else { -        s->opt[OPT_EXTRA_SW].cap = SANE_CAP_INACTIVE; -    } - -    // transparency/scan_film button -    s->opt[OPT_TRANSP_SW].name = "transparency"; -    s->opt[OPT_TRANSP_SW].title = SANE_I18N ("Transparency button"); -    s->opt[OPT_TRANSP_SW].desc = SANE_I18N ("Transparency button"); -    s->opt[OPT_TRANSP_SW].type = SANE_TYPE_BOOL; -    s->opt[OPT_TRANSP_SW].unit = SANE_UNIT_NONE; -    if (model->buttons & GENESYS_HAS_TRANSP_SW) { -        s->opt[OPT_TRANSP_SW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; -    } else { -        s->opt[OPT_TRANSP_SW].cap = SANE_CAP_INACTIVE; -    } +  s->opt[OPT_EXTRA_SW].name = "extra"; +  s->opt[OPT_EXTRA_SW].title = SANE_I18N("Extra button"); +  s->opt[OPT_EXTRA_SW].desc = SANE_I18N("Extra button"); +  s->opt[OPT_EXTRA_SW].type = SANE_TYPE_BOOL; +  s->opt[OPT_EXTRA_SW].unit = SANE_UNIT_NONE; +  if (model->buttons & GENESYS_HAS_EXTRA_SW) +    s->opt[OPT_EXTRA_SW].cap = +      SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; +  else +    s->opt[OPT_EXTRA_SW].cap = SANE_CAP_INACTIVE; + +  /* transparency/scan_film button */ +  s->opt[OPT_TRANSP_SW].name = "transparency"; +  s->opt[OPT_TRANSP_SW].title = SANE_I18N ("Transparency button"); +  s->opt[OPT_TRANSP_SW].desc = SANE_I18N ("Transparency button"); +  s->opt[OPT_TRANSP_SW].type = SANE_TYPE_BOOL; +  s->opt[OPT_TRANSP_SW].unit = SANE_UNIT_NONE; +  if (model->buttons & GENESYS_HAS_TRANSP_SW) +    s->opt[OPT_TRANSP_SW].cap = +      SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; +  else +    s->opt[OPT_TRANSP_SW].cap = SANE_CAP_INACTIVE; + +  /* PDF special function button 1 */ +  s->opt[OPT_PDF1_SW].name = "pdf1"; +  s->opt[OPT_PDF1_SW].title = SANE_I18N ("PDF function button 1"); +  s->opt[OPT_PDF1_SW].desc = SANE_I18N ("PDF function button 1"); +  s->opt[OPT_PDF1_SW].type = SANE_TYPE_BOOL; +  s->opt[OPT_PDF1_SW].unit = SANE_UNIT_NONE; +  if (model->buttons & GENESYS_HAS_PDF1_SW) +    s->opt[OPT_PDF1_SW].cap = +      SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; +  else +    s->opt[OPT_PDF1_SW].cap = SANE_CAP_INACTIVE; + +  /* PDF special function button 2 */ +  s->opt[OPT_PDF2_SW].name = "pdf2"; +  s->opt[OPT_PDF2_SW].title = SANE_I18N ("PDF function button 2"); +  s->opt[OPT_PDF2_SW].desc = SANE_I18N ("PDF function button 2"); +  s->opt[OPT_PDF2_SW].type = SANE_TYPE_BOOL; +  s->opt[OPT_PDF2_SW].unit = SANE_UNIT_NONE; +  if (model->buttons & GENESYS_HAS_PDF2_SW) +    s->opt[OPT_PDF2_SW].cap = +      SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; +  else +    s->opt[OPT_PDF2_SW].cap = SANE_CAP_INACTIVE; + +  /* PDF special function button 3 */ +  s->opt[OPT_PDF3_SW].name = "pdf3"; +  s->opt[OPT_PDF3_SW].title = SANE_I18N ("PDF function button 3"); +  s->opt[OPT_PDF3_SW].desc = SANE_I18N ("PDF function button 3"); +  s->opt[OPT_PDF3_SW].type = SANE_TYPE_BOOL; +  s->opt[OPT_PDF3_SW].unit = SANE_UNIT_NONE; +  if (model->buttons & GENESYS_HAS_PDF3_SW) +    s->opt[OPT_PDF3_SW].cap = +      SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; +  else +    s->opt[OPT_PDF3_SW].cap = SANE_CAP_INACTIVE; + +  /* PDF special function button 4 */ +  s->opt[OPT_PDF4_SW].name = "pdf4"; +  s->opt[OPT_PDF4_SW].title = SANE_I18N ("PDF function button 4"); +  s->opt[OPT_PDF4_SW].desc = SANE_I18N ("PDF function button 4"); +  s->opt[OPT_PDF4_SW].type = SANE_TYPE_BOOL; +  s->opt[OPT_PDF4_SW].unit = SANE_UNIT_NONE; +  if (model->buttons & GENESYS_HAS_PDF4_SW) +    s->opt[OPT_PDF4_SW].cap = +      SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; +  else +    s->opt[OPT_PDF4_SW].cap = SANE_CAP_INACTIVE;    /* calibration needed */    s->opt[OPT_NEED_CALIBRATION_SW].name = "need-calibration"; @@ -5588,7 +5628,7 @@ static void get_option_value(Genesys_Scanner* s, int option, void* val)      auto* dev = s->dev;    unsigned int i;      SANE_Word* table = nullptr; -  std::vector<uint16_t> gamma_table; +    std::vector<std::uint16_t> gamma_table;    unsigned option_size = 0;      const Genesys_Sensor* sensor = nullptr; @@ -5734,6 +5774,10 @@ static void get_option_value(Genesys_Scanner* s, int option, void* val)      case OPT_POWER_SW:      case OPT_EXTRA_SW:      case OPT_TRANSP_SW: +    case OPT_PDF1_SW: +    case OPT_PDF2_SW: +    case OPT_PDF3_SW: +    case OPT_PDF4_SW:          s->dev->cmd_set->update_hardware_sensors(s);          *reinterpret_cast<SANE_Bool*>(val) = s->buttons[genesys_option_to_button(option)].read();          break; @@ -6370,6 +6414,10 @@ GenesysButtonName genesys_option_to_button(int option)      case OPT_POWER_SW: return BUTTON_POWER_SW;      case OPT_EXTRA_SW: return BUTTON_EXTRA_SW;      case OPT_TRANSP_SW: return BUTTON_TRANSP_SW; +    case OPT_PDF1_SW: return BUTTON_PDF1_SW; +    case OPT_PDF2_SW: return BUTTON_PDF2_SW; +    case OPT_PDF3_SW: return BUTTON_PDF3_SW; +    case OPT_PDF4_SW: return BUTTON_PDF4_SW;      default: throw std::runtime_error("Unknown option to convert to button index");      }  } | 
