icon.cpp revision 8fb980df3d9ba01950a763c414479f4bf22ad0d3
/** \file
* SPIcon: Generic icon widget
*/
/*
* Author:
* Lauris Kaplinski <lauris@kaplinski.com>
* Jon A. Cruz <jon@joncruz.org>
* Abhishek Sharma
*
* Copyright (C) 2002 Lauris Kaplinski
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <cstring>
#include <glib.h>
#include <gtkmm.h>
#include <glibmm/fileutils.h>
#include "path-prefix.h"
#include "preferences.h"
#include "inkscape.h"
#include "document.h"
#include "sp-item.h"
#include "display/cairo-utils.h"
#include "display/drawing-context.h"
#include "display/drawing-item.h"
#include "sp-root.h"
#include "icon.h"
// Bring in work-around for Glib versions missing GStatBuf
#else //defined (_MSC_VER) && !defined(_WIN64)
#endif //defined (_MSC_VER) && !defined(_WIN64)
#endif //!GLIB_CHECK_VERSION(2,25,0)
struct IconImpl {
static int getPhysSize(int size);
static GdkPixbuf *loadSvg(std::list<Glib::ustring> const &names, GtkIconSize lsize, unsigned psize);
unsigned r, unsigned g, unsigned b );
static void injectCustomSize();
static void validateCache();
static void setupLegacyNaming();
private:
static GtkWidgetClass *parent_class;
};
static bool sizeDirty = true;
static bool sizeMapDone = false;
static GtkIconSize iconSizeLookup[] = {
GTK_ICON_SIZE_MENU, // for Inkscape::ICON_SIZE_DECORATION
};
class IconCacheItem
{
public:
{}
};
{
if (!type) {
sizeof(SPIconClass),
NULL,
NULL,
NULL,
NULL,
sizeof(SPIcon),
0,
};
}
return type;
}
{
}
{
}
{
}
}
{
}
{
}
}
{
}
{
if (gtk_widget_is_drawable(widget)) {
}
}
{
if ( gtk_widget_is_drawable(widget) ) {
fetchPixbuf( icon );
}
}
return TRUE;
}
// PUBLIC CALL:
{
}
{
if ( icon ) {
}
}
}
}
if (!pb) {
}
}
// if this was loaded from SVG, add it as a builtin icon
if (pb) {
}
}
if (!pb) {
}
if ( !pb ) {
// TODO: We should do something more useful if we can't load the image.
}
return pb;
}
{
}
}
{
}
}
{
if ( dump ) {
g_message("Got a change bump for this icon");
}
sizeDirty = true;
}
{
} else {
result += "\\x";
}
}
return result;
}
{
bool isSized = false;
isSized = true;
}
}
}
return isSized;
}
void IconImpl::validateCache()
{
std::string iconCacheDir = Glib::build_filename(Glib::build_filename(Glib::get_user_cache_dir(), "inkscape"), "icons");
gchar const* potentialFile = *i;
if ( Glib::file_test(potentialFile, Glib::FILE_TEST_EXISTS) && Glib::file_test(potentialFile, Glib::FILE_TEST_IS_REGULAR) ) {
filesFound.push_back(*i);
}
}
unsigned long lastSeen = 0;
} else {
}
}
{
if ( contents ) {
}
contents = 0;
}
}
if ( cacheValid ) {
// Check if any cached rasters are out of date
if ( isSizedSubdir(*it) ) {
if ( Glib::file_test(fullpath, Glib::FILE_TEST_EXISTS) && !Glib::file_test(fullpath, Glib::FILE_TEST_IS_DIR) ) {
cacheValid = false;
}
}
}
}
}
}
}
}
if ( !cacheValid ) {
// Purge existing icons, but not possible future sub-directories.
if ( isSizedSubdir(*it) ) {
if ( Glib::file_test(fullpath, Glib::FILE_TEST_EXISTS) && !Glib::file_test(fullpath, Glib::FILE_TEST_IS_DIR) ) {
}
}
}
}
}
}
} else {
}
// Caching may proceed
} else {
g_warning("Unable to write cache info file.");
}
}
}
void IconImpl::setupLegacyNaming() {
}
{
gint trySize = CLAMP( static_cast<gint>(lsize), 0, static_cast<gint>(G_N_ELEMENTS(iconSizeLookup) - 1) );
if ( !sizeMapDone ) {
}
if ( legacyNames.empty() ) {
}
if ( stockFound ) {
} else {
if ( dump ) {
}
}
if ( img ) {
if ( type == GTK_IMAGE_STOCK ) {
if ( !stockFound ) {
// It's not showing as a stock ID, so assume it will be present internally
// Add a hook to render if set visible before prerender is done.
g_signal_connect( G_OBJECT(img), "map", G_CALLBACK(imageMapCB), GINT_TO_POINTER(static_cast<int>(mappedSize)) );
if ( dump ) {
}
}
img = 0;
if ( dump ) {
g_message( "loaded gtk '%s' %d (GTK_IMAGE_STOCK) %s on %p", name, mappedSize, (stockFound ? "STOCK" : "local"), widget );
}
} else if ( type == GTK_IMAGE_ICON_NAME ) {
img = 0;
// Add a hook to render if set visible before prerender is done.
} else {
}
} else {
if ( dump ) {
}
//g_object_unref( (GObject *)img );
img = 0;
}
}
if ( !widget ) {
//g_message("Creating an SPIcon instance for %s:%d", name, (int)lsize);
}
return widget;
}
// PUBLIC CALL:
{
}
// PUBLIC CALL:
{
GtkWidget *widget = IconImpl::newFull( static_cast<Inkscape::IconSize>(Inkscape::getRegisteredIconSize(size)), oid.c_str() );
if ( widget ) {
if ( GTK_IS_IMAGE(widget) ) {
} else {
}
}
return result;
}
void IconImpl::injectCustomSize()
{
// TODO - still need to handle the case of theme changes and resize, especially as we can't re-register a string.
if ( !sizeMapDone )
{
if ( newSizeEnum ) {
if ( dump ) {
g_message("Registered (%d, %d) <= (%d, %d) as index %d", newWidth, newHeight, width, height, newSizeEnum);
}
} else if ( dump ) {
g_message("size lookup array too small to store entry");
}
}
}
sizeMapDone = true;
}
}
{
} else {
}
return other;
}
// PUBLIC CALL:
int sp_icon_get_phys_size(int size)
{
}
{
static bool init = false;
size = CLAMP( size, static_cast<int>(GTK_ICON_SIZE_MENU), static_cast<int>(Inkscape::ICON_SIZE_DECORATION) );
if ( !sizeMapDone ) {
}
GtkIconSize const gtkSizes[] = {
};
guint const val_ix = (gtkSizes[i] <= GTK_ICON_SIZE_DIALOG) ? (guint)gtkSizes[i] : (guint)Inkscape::ICON_SIZE_DECORATION;
}
}
}
if ( !init ) {
sizeDirty = false;
if ( dump ) {
g_message( "Default icon sizes:" );
}
GtkIconSize const gtkSizes[] = {
};
"GTK_ICON_SIZE_MENU",
"GTK_ICON_SIZE_SMALL_TOOLBAR",
"GTK_ICON_SIZE_LARGE_TOOLBAR",
"GTK_ICON_SIZE_BUTTON",
"GTK_ICON_SIZE_DND",
"GTK_ICON_SIZE_DIALOG",
"inkscape-decoration"
};
for (unsigned i = 0; i < G_N_ELEMENTS(gtkSizes); ++i) {
guint const val_ix = (gtkSizes[i] <= GTK_ICON_SIZE_DIALOG) ? (guint)gtkSizes[i] : (guint)Inkscape::ICON_SIZE_DECORATION;
bool used = false;
used = true;
}
if (dump) {
g_message(" =-- %u size:%d %c(%d, %d) '%s'",
i, gtkSizes[i],
}
// The following is needed due to this documented behavior of gtk_icon_size_lookup:
// gtk_icon_size_lookup(), because themes are free to render the pixbuf however
// they like, including changing the usual size."
if (pb) {
// TODO perhaps check a few more stock icons to get a range on sizes.
if ( newSize > 0 ) {
}
if (dump) {
}
}
}
//g_object_unref(icon);
init = true;
}
}
{
bool unref_image = false;
/* copied from the expose function of GtkImage */
gtk_icon_source_set_size(source, GTK_ICON_SIZE_SMALL_TOOLBAR); // note: this is boilerplate and not used
unref_image = true;
}
if (image) {
// Limit drawing to when we actually have something. Avoids some crashes.
GDK_RGB_DITHER_NORMAL, x, y);
}
}
if (unref_image) {
}
}
{
// TODO: bulia, please look over
gsize bytesWritten = 0;
-1,
&error);
if (!pb) {
// TODO: bulia, please look over
gsize bytesWritten = 0;
-1,
&error);
}
if (pb) {
if (!gdk_pixbuf_get_has_alpha(pb)) {
}
}
}
return pb;
}
{
using Geom::X;
using Geom::Y;
return ret;
}
// takes doc, drawing, icon, and icon name to produce pixels
extern "C" guchar *
unsigned &stride)
{
if (doc) {
// Find bbox in document
{
}
/* This is in document coordinates, i.e. pixels */
if ( dbox ) {
/* Update to renderable state */
double sf = 1.0;
/* Item integer bbox in points */
// NOTE: previously, each rect coordinate was rounded using floor(c + 0.5)
if ( dump ) {
g_message( " box --'%s' (%f,%f)-(%f,%f)", name, (double)ibox.left(), (double)ibox.top(), (double)ibox.right(), (double)ibox.bottom() );
}
/* Find button visible area */
if ( dump ) {
}
{
if ( dump ) {
g_message(" resizing" );
}
if ( dump ) {
g_message( " box2 --'%s' (%f,%f)-(%f,%f)", name, (double)ibox.left(), (double)ibox.top(), (double)ibox.right(), (double)ibox.bottom() );
}
/* Find button visible area */
if ( dump ) {
}
}
}
//dx = (psize - width) / 2;
//dy = (psize - height) / 2;
dx=(dx-width)/2; // watch out for psize, since 'unsigned'-'signed' can cause problems if the result is negative
/* Actual renderable area */
if ( dump ) {
g_message( " area --'%s' (%f,%f)-(%f,%f)", name, (double)area.left(), (double)area.top(), (double)area.right(), (double)area.bottom() );
g_message( " ua --'%s' (%f,%f)-(%f,%f)", name, (double)ua.left(), (double)ua.top(), (double)ua.right(), (double)ua.bottom() );
}
/* Set up pixblock */
/* Render */
// convert to GdkPixbuf format
}
}
}
}
return px;
} // end of sp_icon_doc_icon()
class SVGDocCache
{
public:
{
doc->ensureUpToDate();
}
~SVGDocCache() {
}
unsigned visionkey;
};
{
key += ":";
return key;
}
}
return pb;
}
{
static bool initialized = false;
if (!initialized) {
// Fall back from user prefs dir into system locations.
initialized = true;
}
return sources;
}
// this function renders icons from icons.svg and returns the pixels.
{
// Try each document in turn until we successfully load the icon from one
gchar *doc_filename = *i;
SVGDocCache *info = 0;
// Did we already load this doc?
{
}
}
// Try to load from document.
if ( doc ) {
if ( dump ) {
}
// store into the cache
}
}
if (info) {
for (std::list<Glib::ustring>::const_iterator it = names.begin(); !px && (it != names.end()); ++it ) {
}
}
}
return px;
}
if ( !stockFound ) {
if (dump) {
}
}
}
{
if (!stockFound && !themedFound ) {
gint trySize = CLAMP( static_cast<gint>(lsize), 0, static_cast<gint>(G_N_ELEMENTS(iconSizeLookup) - 1) );
if ( !sizeMapDone ) {
}
// TODO place in a queue that is triggered by other map events
}
}
{
}
}
// returns true if icon needed preloading, false if nothing was done
{
bool loadNeeded = false;
static bool cacheValidated = false;
if (!cacheValidated) {
cacheValidated = true;
if ( useCache ) {
}
}
if ( !get_cached_pixbuf(key) ) {
if (dump) {
}
bool dataLoaded = false;
if ( useCache ) {
// In file encoding:
std::string iconCacheDir = Glib::build_filename(Glib::build_filename(Glib::get_user_cache_dir(), "inkscape"), "icons");
}
potentialFile += ".png";
if ( Glib::file_test(potentialFile, Glib::FILE_TEST_EXISTS) && Glib::file_test(potentialFile, Glib::FILE_TEST_IS_REGULAR) ) {
bool badFile = false;
try {
if (pb) {
dataLoaded = true;
loadNeeded = true;
}
}
//g_warning("FileError [%s]", ex.what().c_str());
badFile = true;
//g_warning("PixbufError [%s]", ex.what().c_str());
// Invalid contents. Remove cached item
badFile = true;
}
if ( badFile ) {
}
}
}
if (!dataLoaded) {
if ( dump ) {
}
}
unsigned stride;
if (px) {
loadNeeded = true;
}
if (useCache) {
try {
//g_warning("FileError [%s]", ex.what().c_str());
//g_warning("PixbufError [%s]", ex.what().c_str());
}
}
} else if (dump) {
}
}
}
else if (dump) {
}
}
return loadNeeded;
}
GdkPixbuf *IconImpl::loadSvg(std::list<Glib::ustring> const &names, GtkIconSize lsize, unsigned psize)
{
if (!pb) {
unsigned stride;
if (px) {
}
}
if ( pb ) {
// increase refcount since we're handing out ownership
}
return pb;
}
unsigned r, unsigned g, unsigned b)
{
int bytesPerPixel = 4;
int spacing = 4;
*(ptr++) = r;
*(ptr++) = g;
*(ptr++) = b;
*(ptr++) = 0xff;
}
}
// point at the last pixel
if ( width > 2 ) {
px[4] = r;
px[5] = g;
px[6] = b;
ptr[-12] = r;
ptr[-11] = g;
ptr[-10] = b;
}
ptr[-4] = r;
ptr[-3] = g;
ptr[-2] = b;
if ( height > 2 ) {
}
}
}
class preRenderItem
{
public:
{}
};
static bool callbackHooked = false;
{
if ( !callbackHooked )
{
callbackHooked = true;
}
}
if ( inkscapeIsCrashing() ) {
// stop
} else if (!pendingRenders.empty()) {
bool workDone = false;
do {
}
return TRUE;
} else {
callbackHooked = false;
return FALSE;
}
}
{
if ( id ) {
for ( std::vector<preRenderItem>::iterator it = pendingRenders.begin(); it != pendingRenders.end(); ++it ) {
}
break;
}
}
}
}
{
if ( iconName ) {
if ( type == GTK_IMAGE_ICON_NAME ) {
{
"icon-name", &iconName,
"icon-size", &iconSize,
NULL);
}
for ( std::vector<preRenderItem>::iterator it = pendingRenders.begin(); it != pendingRenders.end(); ++it ) {
break;
}
}
} else {
}
}
}
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :