375 строки
8.8 KiB
C++
375 строки
8.8 KiB
C++
//========================================================================
|
|
//
|
|
// GDKSplashOutputDev.cc
|
|
//
|
|
// Copyright 2003 Glyph & Cog, LLC
|
|
// Copyright 2004 Red Hat, Inc. (GDK port)
|
|
//
|
|
//========================================================================
|
|
|
|
#include <config.h>
|
|
|
|
#ifdef USE_GCC_PRAGMAS
|
|
#pragma implementation
|
|
#endif
|
|
|
|
#include <goo/gmem.h>
|
|
#include <goo/GooHash.h>
|
|
#include <goo/GooTimer.h>
|
|
#include <splash/SplashTypes.h>
|
|
#include <splash/SplashBitmap.h>
|
|
#include "Object.h"
|
|
#include "ProfileData.h"
|
|
#include "GfxState.h"
|
|
|
|
#include <gdk/gdk.h>
|
|
#include "CairoOutputDev.h"
|
|
|
|
#include "PDFDoc.h"
|
|
#include "GlobalParams.h"
|
|
#include "ErrorCodes.h"
|
|
#include <gtk/gtk.h>
|
|
|
|
|
|
// Mapping
|
|
#include "pdf-operators.c"
|
|
|
|
enum {
|
|
OP_STRING,
|
|
OP_COUNT,
|
|
OP_TOTAL,
|
|
OP_MIN,
|
|
OP_MAX,
|
|
N_COLUMNS
|
|
};
|
|
|
|
class PdfInspector {
|
|
public:
|
|
|
|
PdfInspector(void);
|
|
|
|
void set_file_name (const char *file_name);
|
|
void load (const char *file_name);
|
|
void run (void);
|
|
void error_dialog (const char *error_message);
|
|
void analyze_page (int page);
|
|
|
|
private:
|
|
static void on_file_activated (GtkWidget *widget, PdfInspector *inspector);
|
|
static void on_selection_changed (GtkTreeSelection *selection, PdfInspector *inspector);
|
|
static void on_analyze_clicked (GtkWidget *widget, PdfInspector *inspector);
|
|
|
|
GtkBuilder* builder;
|
|
GtkTreeModel *model;
|
|
PDFDoc *doc;
|
|
CairoOutputDev *output;
|
|
};
|
|
|
|
|
|
|
|
PdfInspector::PdfInspector(void)
|
|
{
|
|
GtkWidget *widget;
|
|
GError* error = NULL;
|
|
|
|
builder = gtk_builder_new ();
|
|
|
|
if (!gtk_builder_add_from_file (builder, "./pdf-inspector.ui", &error))
|
|
{
|
|
g_warning ("Couldn't load builder file: %s", error->message);
|
|
g_error_free (error);
|
|
}
|
|
|
|
widget = GTK_WIDGET (gtk_builder_get_object (builder, "pdf_file_chooser_button"));
|
|
g_signal_connect (widget, "selection-changed", G_CALLBACK (on_file_activated), this);
|
|
|
|
widget = GTK_WIDGET (gtk_builder_get_object (builder, "analyze_button"));
|
|
g_signal_connect (widget, "clicked", G_CALLBACK (on_analyze_clicked), this);
|
|
|
|
// setup the TreeView
|
|
widget = GTK_WIDGET (gtk_builder_get_object (builder, "pdf_tree_view"));
|
|
g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (widget)),
|
|
"changed", G_CALLBACK (on_selection_changed), this);
|
|
model = (GtkTreeModel *)gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_INT,
|
|
G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
|
|
gtk_tree_view_set_model (GTK_TREE_VIEW (widget), model);
|
|
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (widget),
|
|
0, "Operation",
|
|
gtk_cell_renderer_text_new (),
|
|
"text", OP_STRING,
|
|
NULL);
|
|
|
|
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (widget),
|
|
1, "Count",
|
|
gtk_cell_renderer_text_new (),
|
|
"text", OP_COUNT,
|
|
NULL);
|
|
|
|
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (widget),
|
|
2, "Elapsed",
|
|
gtk_cell_renderer_text_new (),
|
|
"text", OP_TOTAL,
|
|
NULL);
|
|
|
|
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (widget),
|
|
3, "Min",
|
|
gtk_cell_renderer_text_new (),
|
|
"text", OP_MIN,
|
|
NULL);
|
|
|
|
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (widget),
|
|
4, "Max",
|
|
gtk_cell_renderer_text_new (),
|
|
"text", OP_MAX,
|
|
NULL);
|
|
|
|
for (int i = 0; i < N_COLUMNS; i++)
|
|
{
|
|
GtkTreeViewColumn *column;
|
|
|
|
column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget), i);
|
|
gtk_tree_view_column_set_sort_column_id (column, i);
|
|
}
|
|
doc = NULL;
|
|
output = new CairoOutputDev();
|
|
output->setPrinting (gFalse);
|
|
|
|
// set up initial widgets
|
|
load (NULL);
|
|
}
|
|
|
|
void
|
|
PdfInspector::set_file_name(const char *file_name)
|
|
{
|
|
GtkWidget *widget;
|
|
|
|
widget = GTK_WIDGET (gtk_builder_get_object (builder, "pdf_file_chooser_button"));
|
|
gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), file_name);
|
|
}
|
|
|
|
void
|
|
PdfInspector::on_file_activated (GtkWidget *widget, PdfInspector *inspector)
|
|
{
|
|
gchar *file_name;
|
|
|
|
file_name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
|
|
if (file_name)
|
|
inspector->load (file_name);
|
|
|
|
g_free (file_name);
|
|
}
|
|
|
|
void
|
|
PdfInspector::on_selection_changed (GtkTreeSelection *selection, PdfInspector *inspector)
|
|
{
|
|
GtkWidget *label;
|
|
size_t i;
|
|
GtkTreeModel *model;
|
|
GtkTreeIter iter;
|
|
gchar *op = NULL;
|
|
|
|
label = GTK_WIDGET (gtk_builder_get_object (inspector->builder, "description_label"));
|
|
gtk_label_set_markup (GTK_LABEL (label), "<i>No Description</i>");
|
|
|
|
if (gtk_tree_selection_get_selected (selection, &model, &iter))
|
|
{
|
|
gtk_tree_model_get (model, &iter,
|
|
OP_STRING, &op,
|
|
-1);
|
|
|
|
}
|
|
|
|
if (op == NULL)
|
|
return;
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (op_mapping); i++)
|
|
{
|
|
|
|
if (!strcmp (op, op_mapping[i].op))
|
|
{
|
|
gchar *text;
|
|
text = g_strdup_printf ("<i>%s</i>", op_mapping[i].description);
|
|
gtk_label_set_markup (GTK_LABEL (label), text);
|
|
g_free (text);
|
|
break;
|
|
}
|
|
}
|
|
|
|
g_free (op);
|
|
}
|
|
|
|
void
|
|
PdfInspector::on_analyze_clicked (GtkWidget *widget, PdfInspector *inspector)
|
|
{
|
|
GtkWidget *spin;
|
|
int page;
|
|
|
|
spin = GTK_WIDGET (gtk_builder_get_object (inspector->builder, "pdf_spin"));
|
|
|
|
page = (int) gtk_spin_button_get_value (GTK_SPIN_BUTTON (spin));
|
|
|
|
inspector->analyze_page (page);
|
|
|
|
}
|
|
|
|
void
|
|
PdfInspector::analyze_page (int page)
|
|
{
|
|
GooHashIter *iter;
|
|
GooHash *hash;
|
|
GooString *key;
|
|
void *p;
|
|
GtkWidget *label;
|
|
char *text;
|
|
cairo_t *cr;
|
|
cairo_surface_t *surface;
|
|
|
|
label = GTK_WIDGET (gtk_builder_get_object (builder, "pdf_total_label"));
|
|
|
|
output->startProfile ();
|
|
gtk_list_store_clear (GTK_LIST_STORE (model));
|
|
|
|
GooTimer timer;
|
|
surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
|
|
doc->getPageCropWidth(page + 1),
|
|
doc->getPageCropHeight(page + 1));
|
|
cr = cairo_create (surface);
|
|
cairo_surface_destroy (surface);
|
|
output->setCairo (cr);
|
|
cairo_destroy (cr);
|
|
doc->displayPage (output, page + 1, 72, 72, 0, gFalse, gTrue, gFalse);
|
|
output->setCairo (NULL);
|
|
|
|
// Total time;
|
|
text = g_strdup_printf ("%g", timer.getElapsed ());
|
|
gtk_label_set_text (GTK_LABEL (label), text);
|
|
g_free (text);
|
|
|
|
// Individual times;
|
|
hash = output->endProfile ();
|
|
hash->startIter(&iter);
|
|
while (hash->getNext(&iter, &key, &p))
|
|
{
|
|
GtkTreeIter tree_iter;
|
|
ProfileData *data_p = (ProfileData *) p;
|
|
|
|
gtk_list_store_append (GTK_LIST_STORE (model), &tree_iter);
|
|
gtk_list_store_set (GTK_LIST_STORE (model), &tree_iter,
|
|
OP_STRING, key->getCString(),
|
|
OP_COUNT, data_p->getCount (),
|
|
OP_TOTAL, data_p->getTotal (),
|
|
OP_MIN, data_p->getMin (),
|
|
OP_MAX, data_p->getMax (),
|
|
-1);
|
|
}
|
|
hash->killIter(&iter);
|
|
deleteGooHash (hash, ProfileData);
|
|
}
|
|
|
|
void
|
|
PdfInspector::load(const char *file_name)
|
|
{
|
|
GtkWidget *spin;
|
|
GtkWidget *button;
|
|
GtkWidget *label;
|
|
|
|
// kill the old PDF file
|
|
if (doc != NULL)
|
|
{
|
|
delete doc;
|
|
doc = NULL;
|
|
}
|
|
|
|
// load the new file
|
|
if (file_name)
|
|
{
|
|
GooString *filename_g;
|
|
|
|
filename_g = new GooString (file_name);
|
|
doc = new PDFDoc(filename_g, 0, 0);
|
|
delete filename_g;
|
|
}
|
|
|
|
if (doc && !doc->isOk())
|
|
{
|
|
this->error_dialog ("Failed to load file.");
|
|
delete doc;
|
|
doc = NULL;
|
|
}
|
|
|
|
spin = GTK_WIDGET (gtk_builder_get_object (builder, "pdf_spin"));
|
|
button = GTK_WIDGET (gtk_builder_get_object (builder, "analyze_button"));
|
|
label = GTK_WIDGET (gtk_builder_get_object (builder, "pdf_total_label"));
|
|
gtk_label_set_text (GTK_LABEL (label), "");
|
|
|
|
if (doc)
|
|
{
|
|
gtk_widget_set_sensitive (spin, TRUE);
|
|
gtk_widget_set_sensitive (button, TRUE);
|
|
gtk_widget_set_sensitive (label, TRUE);
|
|
gtk_spin_button_set_range (GTK_SPIN_BUTTON (spin), 0, doc->getNumPages()-1);
|
|
gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), 0);
|
|
|
|
output->startDoc (doc->getXRef(), doc->getCatalog());
|
|
}
|
|
else
|
|
{
|
|
gtk_widget_set_sensitive (spin, FALSE);
|
|
gtk_widget_set_sensitive (button, FALSE);
|
|
gtk_widget_set_sensitive (label, FALSE);
|
|
}
|
|
}
|
|
|
|
void
|
|
PdfInspector::error_dialog (const char *error_message)
|
|
{
|
|
g_warning ("%s", error_message);
|
|
}
|
|
|
|
void
|
|
PdfInspector::run()
|
|
{
|
|
GtkWidget *dialog;
|
|
|
|
dialog = GTK_WIDGET (gtk_builder_get_object (builder, "pdf_dialog"));
|
|
|
|
gtk_dialog_run (GTK_DIALOG (dialog));
|
|
}
|
|
|
|
|
|
|
|
int
|
|
main (int argc, char *argv [])
|
|
{
|
|
const char *file_name = NULL;
|
|
PdfInspector *inspector;
|
|
|
|
gtk_init (&argc, &argv);
|
|
|
|
globalParams = new GlobalParams();
|
|
globalParams->setProfileCommands (true);
|
|
globalParams->setPrintCommands (true);
|
|
|
|
if (argc == 2)
|
|
file_name = argv[1];
|
|
else if (argc > 2)
|
|
{
|
|
fprintf (stderr, "usage: %s [PDF-FILE]\n", argv[0]);
|
|
return -1;
|
|
}
|
|
|
|
inspector = new PdfInspector ();
|
|
|
|
if (file_name)
|
|
inspector->set_file_name (file_name);
|
|
|
|
inspector->run ();
|
|
|
|
delete inspector;
|
|
delete globalParams;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|