/*! \brief Create picture OBJECT from character string.
 *  \par Function Description
 *  Parses \a first_line and subsequent lines from \a tb, and returns
 *  a newly-created picture #OBJECT.
 *
 *  \param [in]  toplevel       The TOPLEVEL object.
 *  \param [in]  first_line      Character string with picture description.
 *  \param [in]  tb              Text buffer to load embedded data from.
 *  \param [in]  release_ver     libgeda release version number.
 *  \param [in]  fileformat_ver  libgeda file format version number.
 *  \return A pointer to the new picture object, or NULL on error.
 */
OBJECT *o_picture_read (TOPLEVEL *toplevel,
                        const char *first_line,
                        TextBuffer *tb,
                        unsigned int release_ver,
                        unsigned int fileformat_ver,
                        GError **err)
{
  OBJECT *new_obj;
  int x1, y1;
  int width, height, angle;
  int mirrored, embedded;
  int num_conv;
  gchar type;
  const gchar *line = NULL;
  gchar *filename;
  gchar *file_content = NULL;
  guint file_length = 0;

  num_conv = sscanf(first_line, "%c %d %d %d %d %d %d %d\n",
                    &type, &x1, &y1, &width, &height, &angle, &mirrored, &embedded);

  if (num_conv != 8) {
    g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse picture definition"));
    return NULL;
  }

  if (width == 0 || height == 0) {
    s_log_message(_("Found a zero width/height picture "
                    "[ %1$c %2$d %3$d %4$d %5$d ]"),
                  type, x1, y1, width, height);
  }

  if ( (mirrored > 1) || (mirrored < 0)) {
    s_log_message(_("Found a picture with a wrong 'mirrored' parameter: %1$d."),
                  mirrored);
    s_log_message(_("Setting mirrored to 0."));
    mirrored = 0;
  }

  if ( (embedded > 1) || (embedded < 0)) {
    s_log_message(_("Found a picture with a wrong 'embedded' parameter: %1$d."),
                  embedded);
    s_log_message(_("Setting embedded to 0."));
    embedded = 0;
  }

  switch(angle) {

    case(0):
    case(90):
    case(180):
    case(270):
    break;

    default:
      s_log_message(_("Found an unsupported picture angle [ %1$d ]"), angle);
      s_log_message(_("Setting angle to 0."));
      angle=0;
      break;

  }

  filename = g_strdup(s_textbuffer_next_line(tb));
  filename = geda_string_remove_ending_newline (filename);

  /* Handle empty filenames */
  if (strlen (filename) == 0) {
    s_log_message (_("Found an image with no filename."));
    g_free (filename);
    filename = NULL;
  }

  if (embedded == 1) {
    GString *encoded_picture=g_string_new("");
    char finished = 0;

    /* Read the encoded picture */
    do {

      line = s_textbuffer_next_line(tb);
      if (line == NULL) break;

      if (strcmp (line, ".\n") != 0) {
        encoded_picture = g_string_append (encoded_picture, line);
      } else {
        finished = 1;
      }
    } while (finished == 0);

    /* Decode the picture */
    if (encoded_picture != NULL) {
      file_content = s_encoding_base64_decode(encoded_picture->str,
                                              encoded_picture->len,
                                              &file_length);
      g_string_free (encoded_picture, TRUE);
    }

    if (file_content == NULL) {
      s_log_message (_("Failed to load image from embedded data [%1$s]: %2$s"),
                     filename, _("Base64 decoding failed."));
      s_log_message (_("Falling back to file loading. Picture unembedded."));
      embedded = 0;
    }
  }

  /* create the picture */
  /* The picture is described by its upper left and lower right corner */
  new_obj = o_picture_new (toplevel, file_content, file_length, filename,
                           type,
                           x1, y1+height, x1+width, y1,
                           angle, mirrored, embedded);

  g_free (file_content);
  g_free (filename);

  return new_obj;
}
Beispiel #2
0
/*! \brief Create path OBJECT from character string.
 *  \par Function Description
 *  This function creates a path OBJECT from the character string
 *  <B>*buf</B> and a number of lines following that describing the
 *  path, read from <B>*tb</B>.
 *
 *  Depending on <B>*version</B>, the correct file format is considered.
 *  Currently two file format revisions are supported :
 *  <DL>
 *    <DT>*</DT><DD>the file format used until 20010704 release.
 *    <DT>*</DT><DD>the file format used for the releases after 20010704.
 *  </DL>
 *
 *  \param [in]  toplevel       The TOPLEVEL object.
 *  \param [in]  first_line      Character string with path description.
 *  \param [in]  tb              Text buffer containing the path string.
 *  \param [in]  release_ver     libgeda release version number.
 *  \param [in]  fileformat_ver  libgeda file format version number.
 *  \return A pointer to the new path object, or NULL on error;
 */
OBJECT *o_path_read (TOPLEVEL *toplevel,
                     const char *first_line, TextBuffer *tb,
                     unsigned int release_ver, unsigned int fileformat_ver, GError **err)
{
  OBJECT *new_obj;
  char type;
  int color;
  int line_width, line_space, line_length;
  int line_end;
  int line_type;
  int fill_type, fill_width, angle1, pitch1, angle2, pitch2;
  int num_lines = 0;
  int i;
  char *string;
  GString *pathstr;

  /*
   * The current path format to describe a line is a space separated
   * list of characters and numbers in plain ASCII on a single path.
   * The meaning of each item is described in the file format documentation.
   */
  /* Allocate enough space */
  if (sscanf (first_line, "%c %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
	      &type, &color, &line_width, &line_end, &line_type,
	      &line_length, &line_space, &fill_type, &fill_width, &angle1,
	      &pitch1, &angle2, &pitch2, &num_lines) != 14) {
    g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse path object"));
    return NULL;
  }

  /*
   * Checks if the required color is valid.
   */
  if (color < 0 || color > MAX_COLORS) {
    s_log_message (_("Found an invalid color [ %1$s ]"), first_line);
    s_log_message (_("Setting color to default color."));
    color = DEFAULT_COLOR;
  }

  /*
   * A path is internally described by its two ends. A new object is
   * allocated, initialized and added to the list of objects. Its path
   * type is set according to the values of the fields on the path.
   */

  pathstr = g_string_new ("");
  for (i = 0; i < num_lines; i++) {
    const gchar *line;

    line = s_textbuffer_next_line (tb);

    if (line == NULL) {
      g_set_error (err, EDA_ERROR, EDA_ERROR_PARSE, _("Unexpected end-of-file when reading path"));
      return NULL;
    }

    pathstr = g_string_append (pathstr, line);
  }

  /* retrieve the character string from the GString */
  string = g_string_free (pathstr, FALSE);
  string = geda_string_remove_ending_newline (string);

  /* create a new path */
  new_obj = geda_path_object_new (toplevel, type, color, string);
  g_free (string);

  /* set its line options */
  o_set_line_options (toplevel,
                      new_obj,
                      (OBJECT_END) line_end,
                      (OBJECT_TYPE) line_type,
                      line_width,
                      line_length,
                      line_space);
  /* set its fill options */
  o_set_fill_options (toplevel,
                      new_obj,
                      (OBJECT_FILLING) fill_type,
                      fill_width,
                      pitch1,
                      angle1,
                      pitch2,
                      angle2);

  return new_obj;
}
Beispiel #3
0
/*! \brief read a text object from a char buffer
 *  \par Function Description
 *  This function reads a text object from the textbuffer \a tb and
 *  the text starting with the line \a firstline.
 *  If the line object was read successfully, a new object is
 *  create and appended to the \a object_list.
 *
 *  \param [in] toplevel     The TOPLEVEL object
 *  \param [in] first_line   the first line of the text
 *  \param [in] tb           a text buffer (usually a line of a schematic file)
 *  \param [in] release_ver  The release number gEDA
 *  \param [in] fileformat_ver a integer value of the file format
 *  \return The object list, or NULL on error.
 */
OBJECT*
o_text_read (TOPLEVEL *toplevel,
             const char *first_line,
             TextBuffer *tb,
             unsigned int release_ver,
             unsigned int fileformat_ver,
             GError **err)
{
  OBJECT *new_obj;
  char type;
  int x, y;
  int color;
  int size;
  int visibility;
  int show_name_value;
  int angle;
  int alignment;
  int num_lines = 0;
  int i;
  char* string = NULL;
  GString *textstr;

  if (fileformat_ver >= 1) {
    if (sscanf(first_line, "%c %d %d %d %d %d %d %d %d %d\n", &type, &x, &y,
	       &color, &size,
	       &visibility, &show_name_value,
	       &angle, &alignment, &num_lines) != 10) {
      g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse text object"));
      return NULL;
    }
  } else if (release_ver < VERSION_20000220) {
    /* yes, above less than (not less than and equal) is correct. The format */
    /* change occurred in 20000220 */
    if (sscanf(first_line, "%c %d %d %d %d %d %d %d\n", &type, &x, &y,
	       &color, &size,
	       &visibility, &show_name_value,
	       &angle) != 8) {
      g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse text object"));
      return NULL;
    }
    alignment = LOWER_LEFT; /* older versions didn't have this */
    num_lines = 1; /* only support a single line */
  } else {
    if (sscanf(first_line, "%c %d %d %d %d %d %d %d %d\n", &type, &x, &y,
	       &color, &size,
	       &visibility, &show_name_value,
           &angle, &alignment) != 9) {
      g_set_error (err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse text object"));
      return NULL;
    }
    num_lines = 1; /* only support a single line */
  }

  if (size < MINIMUM_TEXT_SIZE) {
    s_log_message (_("Found an invalid text size [ %1$s ]"), first_line);
    size = DEFAULT_TEXT_SIZE;
    s_log_message (_("Setting text size to %1$d."), size);
  }

  if (!geda_angle_is_ortho (angle)) {
    s_log_message (_("Found an unsupported text angle [ %1$s ]"), first_line);
    angle = geda_angle_make_ortho (angle);
    s_log_message (_("Setting angle to %1$d."), angle);
  }

  switch(alignment) {
    case(LOWER_LEFT):
    case(MIDDLE_LEFT):
    case(UPPER_LEFT):
    case(LOWER_MIDDLE):
    case(MIDDLE_MIDDLE):
    case(UPPER_MIDDLE):
    case(LOWER_RIGHT):
    case(MIDDLE_RIGHT):
    case(UPPER_RIGHT):

    break;

    default:
      s_log_message (_("Found an unsupported text alignment [ %1$s ]"),
                     first_line);
      alignment = LOWER_LEFT;
      s_log_message(_("Setting alignment to LOWER_LEFT."));
      break;
  }

  if (color < 0 || color > MAX_COLORS) {
    s_log_message(_("Found an invalid color [ %1$s ]"), first_line);
    color = DEFAULT_COLOR;
    s_log_message(_("Setting color to default color."));
  }

  g_assert(num_lines && num_lines > 0);

  textstr = g_string_new ("");
  for (i = 0; i < num_lines; i++) {
    const gchar *line;

    line = s_textbuffer_next_line (tb);

    if (line == NULL) {
      g_string_free (textstr, TRUE);
      g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Unexpected end-of-file after %1$d lines"), i);
      return NULL;
    }

    textstr = g_string_append (textstr, line);
  }
  /* retrieve the character string from the GString */
  string = g_string_free (textstr, FALSE);

  string = geda_string_remove_ending_newline (string);

  /* convert the character string to UTF-8 if necessary */
  if (!g_utf8_validate (string, -1, NULL)) {
    /* if it is not utf-8, it is ISO_8859-15 */
    gchar *tmp = g_convert (string, strlen (string),
                            "UTF-8", "ISO_8859-15",
                            NULL, NULL, NULL);
    if (tmp == NULL) {
      fprintf (stderr, "Failed to convert text string to UTF-8: %1$s.\n",
               string);
    } else {
      /* successfully converted string, now use tmp as string */
      g_free (string);
      string = tmp;
    }
  }

  new_obj = geda_text_object_new (toplevel,
                                  color,
                                  x,
                                  y,
                                  alignment,
                                  angle,
                                  string,
                                  size,
                                  visibility,
                                  show_name_value);
  g_free(string);

  return new_obj;
}