/*! \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; }
/*! \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; }
/*! \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; }