drawing-image.cpp revision 82d58ca5824c10cdb322746bdc46a5fe438fc0a1
/**
* @file
* Bitmap image belonging to an SVG drawing.
*//*
* Authors:
* Krzysztof KosiĆski <tweenk.pl@gmail.com>
*
* Copyright (C) 2011 Authors
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include "display/cairo-utils.h"
#include "display/drawing-context.h"
#include "display/drawing-image.h"
#include "preferences.h"
#include "style.h"
namespace Inkscape {
, _new_surface(NULL)
{}
{
if (_style)
if (_pixbuf) {
}
}
void
{
// when done in this order, it won't break if pb == image->pixbuf and the refcount is 1
g_object_ref (pb);
}
}
_markForUpdate(STATE_ALL, false);
}
void
{
}
void
{
_markForUpdate(STATE_ALL, false);
}
void
{
_origin = o;
_markForUpdate(STATE_ALL, false);
}
void
{
_markForUpdate(STATE_ALL, false);
}
DrawingImage::bounds() const
{
return ret;
}
unsigned
{
// Calculate bbox
if (_pixbuf) {
_bbox = r.roundOutwards();
} else {
}
return STATE_ALL;
}
unsigned DrawingImage::_renderItem(DrawingContext &ct, Geom::IntRect const &/*area*/, unsigned /*flags*/, DrawingItem * /*stop_at*/)
{
if (!outline) {
/////////////////////////////////////////////////////////////////////////////
// BEGIN: Hack to avoid Cairo bug
// The total transform (which is RIGHT-multiplied with the item points to get display points) equals:
// scale*translate_origin*_ctm = scale*translate(origin)*expansion*expansionInv*_ctm
// = scale*expansion*translate(origin*expansion)*expansionInv*_ctm
// To avoid a Cairo bug, we handle the scale*expansion part ourselves.
if (_scale[Geom::X]*expansion[Geom::X]*orgwidth*255.0<1.0 || _scale[Geom::Y]*expansion[Geom::Y]*orgheight*255.0<1.0) {
// Resized image too small to actually see anything
return RENDER_OK;
}
// Split scale*expansion in a part that is <= 1.0 and a part that is >= 1.0. We only take care of the part <= 1.0.
Geom::Scale scaleExpansionSmall(std::min<Geom::Coord>(fabs(_scale[Geom::X]*expansion[Geom::X]),1),std::min<Geom::Coord>(fabs(_scale[Geom::Y]*expansion[Geom::Y]),1));
Geom::Scale scaleExpansionLarge(_scale[Geom::X]*expansion[Geom::X]/scaleExpansionSmall[Geom::X],_scale[Geom::Y]*expansion[Geom::Y]/scaleExpansionSmall[Geom::Y]);
// Just use _surface directly.
// Rescaled image is sufficiently different from cached image to recompute
// This essentially considers an image to be composed of rectangular pixels (box kernel) and computes the least-squares approximation of the original.
// When the scale factor is really large or small this essentially results in using a box filter, while for scale factors approaching 1 it is more like a "tent" kernel.
// Although the quality of the result is not great, it is typically better than an ordinary box filter, and it is guaranteed to preserve the overall brightness of the image.
// The best improvement would probably be to do the same kind of thing based on a tent kernel, but that's quite a bit more complicated, and probably not worth the trouble for a hack like this.
for(int x=0; x<orgwidth; x++) {
double coordBegin = x*static_cast<double>(scaleExpansionSmall[Geom::X]); // x-coord in target coordinates where the current source pixel begins
double coordEnd = (x+1)*static_cast<double>(scaleExpansionSmall[Geom::X]); // x-coord in target coordinates where the current source pixel ends
int begin = static_cast<int>(floor(coordBegin)); // First pixel (x-coord) affected by the current source pixel
int end = static_cast<int>(ceil(coordEnd)); // First pixel (x-coord) NOT affected by the current source pixel (a zero contribution is counted as not affecting the pixel)
// Set xBegin if this is the first source pixel contributing to the target pixel.
// This computes the fraction of the current target pixel (at nx) that is covered by the source pixel (at x).
xCoefs[nx].push_back(static_cast<float>(std::min<double>(nx+1,coordEnd) - std::max<double>(nx,coordBegin)));
}
}
for(int y=0; y<orgheight; y++) {
double coordBegin = y*static_cast<double>(scaleExpansionSmall[Geom::Y]); // y-coord in target coordinates where the current source pixel begins
double coordEnd = (y+1)*static_cast<double>(scaleExpansionSmall[Geom::Y]); // y-coord in target coordinates where the current source pixel ends
int begin = static_cast<int>(floor(coordBegin)); // First pixel (y-coord) affected by the current source pixel
int end = static_cast<int>(ceil(coordEnd)); // First pixel (y-coord) NOT affected by the current source pixel (a zero contribution is counted as not affecting the pixel)
// Set yBegin if this is the first source pixel contributing to the target pixel.
// This computes the fraction of the current target pixel (at ny) that is covered by the source pixel (at y).
yCoefs[ny].push_back(static_cast<float>(std::min<double>(ny+1,coordEnd) - std::max<double>(ny,coordBegin)));
}
}
for(int y=0; y<newheight; y++) {
for(int x=0; x<newwidth; x++) {
float tempSum[4] = {0,0,0,0};
for(int c=0; c<4; c++) {
}
}
}
for(int c=0; c<4; c++) {
}
}
}
} else {
// No need to regenerate, but we do draw from _new_surface.
}
// END: Hack to avoid Cairo bug
/////////////////////////////////////////////////////////////////////////////
// TODO: If Cairo's problems are gone, uncomment the following:
//ct.translate(_origin);
//ct.scale(_scale);
//ct.setSource(_surface, 0, 0);
//ct.paint(_opacity);
} else { // outline; draw a rect instead
// the box
// the diagonals
}
}
return RENDER_OK;
}
/** Calculates the closest distance from p to the segment a1-a2*/
static double
{
// calculate sides of the triangle and their squares
double a_2 = a * a;
// if one of the angles at the base is > 90, return the corresponding side
// otherwise calculate the height to the base
}
{
if (outline) {
// frame
// diagonals
return NULL;
} else {
return NULL;
return NULL;
// pick if the image is less than 99% transparent
}
}
} // end namespace Inkscape
/*
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 :