예제 #1
0
/**
 * gimp_image_arrange_objects:
 * @image:                The #GimpImage to which the objects belong.
 * @list:                 A #GList of objects to be aligned.
 * @alignment:            The point on each target object to bring into alignment.
 * @reference:            The #GObject to align the targets with, or #NULL.
 * @reference_alignment:  The point on the reference object to align the target item with..
 * @offset:               How much to shift the target from perfect alignment..
 *
 * This function shifts the positions of a set of target objects, which can be
 * "items" or guides, to bring them into a specified type of alignment with a
 * reference object, which can be an item, guide, or image.  If the requested
 * alignment does not make sense (i.e., trying to align a vertical guide vertically),
 * nothing happens and no error message is generated.
 *
 * The objects in the list are sorted into increasing order before
 * being arranged, where the order is defined by the type of alignment
 * being requested.  If the @reference argument is #NULL, then the first
 * object in the sorted list is used as reference.
 *
 * When there are multiple target objects, they are arranged so that the spacing
 * between consecutive ones is given by the argument @offset.
 */
void
gimp_image_arrange_objects (GimpImage         *image,
                            GList             *list,
                            GimpAlignmentType  alignment,
                            GObject           *reference,
                            GimpAlignmentType  reference_alignment,
                            gint               offset)
{
  gboolean do_x               = FALSE;
  gboolean do_y               = FALSE;
  gint     z0                 = 0;
  GList   *object_list;

  g_return_if_fail (GIMP_IS_IMAGE (image));
  g_return_if_fail (G_IS_OBJECT (reference) || reference == NULL);

  /* get offsets used for sorting */
  switch (alignment)
    {
      /* order vertically for horizontal alignment */
    case GIMP_ALIGN_LEFT:
    case GIMP_ALIGN_HCENTER:
    case GIMP_ALIGN_RIGHT:
      do_x = TRUE;
      compute_offsets (list, GIMP_ALIGN_TOP);
      break;
      /* order horizontally for horizontal arrangement */
    case GIMP_ARRANGE_LEFT:
    case GIMP_ARRANGE_HCENTER:
    case GIMP_ARRANGE_RIGHT:
      do_x = TRUE;
      compute_offsets (list, alignment);
      break;
      /* order horizontally for vertical alignment */
    case GIMP_ALIGN_TOP:
    case GIMP_ALIGN_VCENTER:
    case GIMP_ALIGN_BOTTOM:
      do_y = TRUE;
      compute_offsets (list, GIMP_ALIGN_LEFT);
      break;
      /* order vertically for vertical arrangement */
    case GIMP_ARRANGE_TOP:
    case GIMP_ARRANGE_VCENTER:
    case GIMP_ARRANGE_BOTTOM:
      do_y = TRUE;
      compute_offsets (list, alignment);
      break;
    }

  object_list = sort_by_offset (list);

  /* now get offsets used for aligning */
  compute_offsets (list, alignment);

  if (reference == NULL)
    {
      reference = G_OBJECT (object_list->data);
      object_list = g_list_next (object_list);
    }
  else
    compute_offset (reference, reference_alignment);

  z0 = GPOINTER_TO_INT (g_object_get_data (reference, "align-offset"));

  if (object_list)
    {
      GList *l;
      gint   n;

      /* FIXME: undo group type is wrong */
      gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_ITEM_DISPLACE,
                                   C_("undo-type", "Arrange Objects"));

      for (l = object_list, n = 1; l; l = g_list_next (l), n++)
        {
          GObject *target          = G_OBJECT (l->data);
          gint     xtranslate      = 0;
          gint     ytranslate      = 0;
          gint     z1;

          z1 = GPOINTER_TO_INT (g_object_get_data (target,
                                                    "align-offset"));

          if (do_x)
            xtranslate = z0 - z1 + n * offset;

          if (do_y)
            ytranslate = z0 - z1 + n * offset;

          /* now actually align the target object */
          if (GIMP_IS_ITEM (target))
            {
              gimp_item_translate (GIMP_ITEM (target),
                                   xtranslate, ytranslate, TRUE);
            }
          else if (GIMP_IS_GUIDE (target))
            {
              GimpGuide *guide = GIMP_GUIDE (target);

              switch (gimp_guide_get_orientation (guide))
                {
                case GIMP_ORIENTATION_VERTICAL:
                  gimp_image_move_guide (image, guide, z1 + xtranslate, TRUE);
                  break;

                case GIMP_ORIENTATION_HORIZONTAL:
                  gimp_image_move_guide (image, guide, z1 + ytranslate, TRUE);
                  break;

                default:
                  break;
                }
            }
        }

      gimp_image_undo_group_end (image);
    }

  g_list_free (object_list);
}
예제 #2
0
void analyze_CPK(FILE *infile, long file_length, struct cpk_file *file, int new_file_count)
{
    const long CpkHeader_offset = 0x0;
    char *toc_string_table = NULL;

    /* check header */
    {
        unsigned char buf[4];
        static const char CPK_signature[4] = "CPK "; /* intentionally unterminated */
        get_bytes_seek(CpkHeader_offset, infile, buf, 4);
        CHECK_ERROR (memcmp(buf, CPK_signature, sizeof(CPK_signature)), "CPK signature not found");
    }

    /* check CpkHeader */
    {
        struct utf_query_result result = query_utf_nofail(infile, CpkHeader_offset+0x10, NULL);

        CHECK_ERROR (result.rows != 1, "wrong number of rows in CpkHeader");
    }

    /* get TOC offset */
    long toc_offset = query_utf_8byte(infile, CpkHeader_offset+0x10, 0, "TocOffset");

    /* get content offset */
    long content_offset = query_utf_8byte(infile, CpkHeader_offset+0x10, 0, "ContentOffset");

    /* get file count from CpkHeader */
    long CpkHeader_count = query_utf_4byte(infile, CpkHeader_offset+0x10, 0, "Files");

	#ifdef DEBUG
		printf("(Debug)TocOffset: %d\n(Debug)ContentOffset: %d\n(Debug)Files(Count): %d\n",toc_offset,content_offset,CpkHeader_count);
	#endif

    /* check TOC header */
    {
        unsigned char buf[4];
        static const char TOC_signature[4] = "TOC "; /* intentionally unterminated */
        get_bytes_seek(toc_offset, infile, buf, 4);
        CHECK_ERROR (memcmp(buf, TOC_signature, sizeof(TOC_signature)), "TOC signature not found");
    }

    /* get TOC entry count, string table offset */
    long toc_entries;
    long toc_string_table_offset;
    long toc_string_table_size;
    {
        struct utf_query_result result = query_utf_nofail(infile, toc_offset+0x10, NULL);

        toc_entries = result.rows;
        toc_string_table_offset = toc_offset + 0x10 + 8 + result.string_table_offset;
        toc_string_table_size = result.data_offset - result.string_table_offset;
    }

	#ifdef DEBUG
		printf("(Debug)TocEntries: %d\n(Debug)TocStringTableOffset: %d\n(Debug)TocStringTableSize:%d\n",toc_entries,toc_string_table_offset,toc_string_table_size);
	#endif

    /* check that counts match */
    CHECK_ERROR( toc_entries != CpkHeader_count, "CpkHeader file count and TOC entry count do not match" );

    /* load string table */
    toc_string_table = malloc(toc_string_table_size + 1);
    {
        CHECK_ERRNO(!toc_string_table, "malloc");
        memset(toc_string_table, 0, toc_string_table_size+1);
        get_bytes_seek(toc_string_table_offset, infile,
                (unsigned char *)toc_string_table, toc_string_table_size);
    }

    /* find files in cpk */
    for (int i = 0; i < toc_entries; i++)
    {
        /* get file name */
        const char *file_name = query_utf_string(infile, toc_offset+0x10, i, "FileName", toc_string_table);
        
		const char *dir_name=query_utf_string(infile,toc_offset+0x10,i,"DirName",toc_string_table);
		
		/* to query a file with relative path, remember to free it */
		char* query_file=malloc(strlen(dir_name)+strlen(file_name)+2);

		strcpy(query_file,dir_name);

		char sep[]="/";
		
		strcat(query_file,sep);

		strcat(query_file,file_name);

        int entry_num = contains_file_name(query_file, file, new_file_count);
        if (entry_num >= 0)
        {
			#ifdef DEBUG
				printf("(Debug)FileName length:%d\n(Debug)DirName length:%d\n",strlen(file_name),strlen(dir_name));
				printf("(Debug)query file location:%s\n",query_file);
			#endif

            printf("Found %s/%s in cpk\n",dir_name, file_name);

            /* get file offset */
            file[entry_num].orig_offset = content_offset + query_utf_8byte(infile, toc_offset+0x10, i, "FileOffset");

            /* get file size */
            file[entry_num].orig_size = query_utf_4byte(infile, toc_offset+0x10, i, "FileSize");

            /* save index */
            file[entry_num].index = i;
            file[entry_num].found = 1;
			#ifdef DEBUG
				printf("(Debug)EntryNum:%d\n",entry_num);
			#endif
         }

		/* free the query_file to avoid leak */
		if(query_file)
			free(query_file);
    }

    sort_by_offset(file, new_file_count);
 
    FILE *outfile = fopen("out.cpk", "w+b");

    printf("Starting file copy\n");
    long current = 0;
    for (int i = 0; i < new_file_count; i++)
    {
        if (file[i].found)
        {
            /* copy from infile to start of current new file */
            dump(infile, outfile, current, file[i].orig_offset-current);
            current = file[i].orig_offset;
            
            /* open new file and copy data */
            FILE *newfile = fopen(file[i].location, "rb");
            CHECK_ERRNO(!newfile, "fopen");
            CHECK_ERRNO(fseek(newfile, 0 , SEEK_END) != 0, "fseek");
            file[i].new_size = ftell(newfile);
            CHECK_ERRNO(file_length == -1, "ftell");
            rewind(infile);
            printf("Copying %s(file name:%s)\n", file[i].location,file[i].filename);
            dump(newfile, outfile, 0, file[i].new_size);
            printf("Finished copying %s(file name:%s)\n", file[i].location,file[i].filename);
            fclose(newfile);
            
            /* update information */
            current += file[i].orig_size;
            file[i].copied = 1;
            file[i].offset_diff = file[i].new_size -file[i].orig_size;
        }
    }
     
    /* copy remaining data */
    dump(infile, outfile, current, file_length-current);
    printf("Finished file copy\n");
     
    /* fix toc_offset */
    toc_offset = fix_offset(outfile, CpkHeader_offset+0x10, 0, 0, "TocOffset", file, new_file_count);
    printf("Fixed toc offset\n");

    /* fix file offsets */
    for (int i = 0; i < toc_entries; i++)
        fix_offset(outfile, toc_offset+0x10, content_offset, i, "FileOffset", file, new_file_count);
    printf("Fixed file offsets\n");

    /* fix file sizes */
    for (int i = 0; i < new_file_count; i++)
        fix_file_sizes(outfile, toc_offset+0x10, file, i);

    printf("Finished replacing files and fixing data\n");
    CHECK_ERRNO(fclose(outfile) != 0, "fclose");

    if (toc_string_table)
    {
        free(toc_string_table);
        toc_string_table = NULL;
    }
}