summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: af7ab56)
raw | patch | inline | side by side (parent: af7ab56)
author | miklosh <miklosh@users.sourceforge.net> | |
Thu, 9 Aug 2007 17:21:41 +0000 (17:21 +0000) | ||
committer | miklosh <miklosh@users.sourceforge.net> | |
Thu, 9 Aug 2007 17:21:41 +0000 (17:21 +0000) |
src/extension/internal/pdfinput/svg-builder.cpp | patch | blob | history | |
src/extension/internal/pdfinput/svg-builder.h | patch | blob | history |
diff --git a/src/extension/internal/pdfinput/svg-builder.cpp b/src/extension/internal/pdfinput/svg-builder.cpp
index 08719afd023f500ca7201987b8b6e6abd87977cb..7a63ba41510a4a9d27c5529e07bf97f7dc59c606 100644 (file)
}
static gchar *svgConvertGfxRGB(GfxRGB *color) {
- double r = color->r / 65535.0;
- double g = color->g / 65535.0;
- double b = color->b / 65535.0;
+ double r = (double)color->r / 65535.0;
+ double g = (double)color->g / 65535.0;
+ double b = (double)color->b / 65535.0;
return svgConvertRGBToText(r, g, b);
}
@@ -396,7 +396,7 @@ void SvgBuilder::addShadedFill(GfxShading *shading, double *matrix, GfxPath *pat
// Set style
SPCSSAttr *css = sp_repr_css_attr_new();
- gchar *id = _createGradient(shading, matrix);
+ gchar *id = _createGradient(shading, matrix, true);
if (id) {
gchar *urltext = g_strdup_printf ("url(#%s)", id);
sp_repr_css_set_property(css, "fill", urltext);
/**
* \brief Creates a linear or radial gradient from poppler's data structure
+ * \param shading poppler's data structure for the shading
+ * \param matrix gradient transformation, can be null
+ * \param for_shading true if we're creating this for a shading operator; false otherwise
* \return id of the created object
*/
-gchar *SvgBuilder::_createGradient(GfxShading *shading, double *matrix) {
+gchar *SvgBuilder::_createGradient(GfxShading *shading, double *matrix, bool for_shading) {
Inkscape::XML::Node *gradient;
Function *func;
int num_funcs;
return NULL;
}
gradient->setAttribute("gradientUnits", "userSpaceOnUse");
- // Flip the gradient transform around the y axis
+ // If needed, flip the gradient transform around the y axis
if (matrix) {
NR::Matrix pat_matrix(matrix[0], matrix[1], matrix[2], matrix[3],
matrix[4], matrix[5]);
- NR::Matrix flip(1.0, 0.0, 0.0, -1.0, 0.0, _height * PT_PER_PX);
- pat_matrix *= flip;
+ if ( !for_shading && _is_top_level ) {
+ NR::Matrix flip(1.0, 0.0, 0.0, -1.0, 0.0, _height * PT_PER_PX);
+ pat_matrix *= flip;
+ }
gchar *transform_text = sp_svg_transform_write(pat_matrix);
gradient->setAttribute("gradientTransform", transform_text);
g_free(transform_text);
gradient->setAttribute("spreadMethod", "pad");
}
- if ( num_funcs > 1 || !_addStopsToGradient(gradient, func, 1.0) ) {
+ if ( num_funcs > 1 || !_addGradientStops(gradient, shading, func) ) {
Inkscape::GC::release(gradient);
return NULL;
}
}
#define EPSILON 0.0001
-bool SvgBuilder::_addSamplesToGradient(Inkscape::XML::Node *gradient,
- Function *func, double offset0,
- double offset1, double opacity) {
-
- // Check whether this sampled function can be converted to color stops
- int sample_size = 0;
- int num_comps = func->getOutputSize();
- double *samples = NULL;
- if ( func->getType() == 0 ) { // Sampled function
- SampledFunction *sampled_func = (SampledFunction*)func;
- sample_size = sampled_func->getSampleSize(0);
- if ( sample_size != 2 || num_comps != 3 ) {
- return false;
- }
- samples = sampled_func->getSamples();
- } else if ( func->getType() == 2 ) { // Exponential function
- sample_size = 1;
- if ( num_comps != 1 && num_comps != 3 ) {
- return false;
- }
- double *exp_output = new double[2 * num_comps];
- ExponentialFunction *exp_func = (ExponentialFunction*)func;
- double x = 0.0;
- for ( int i = 0 ; i < 2 * num_comps ; i += num_comps ) {
- if ( i >= num_comps ) {
- x = 1.0;
- }
- exp_func->transform(&x, &exp_output[i]);
- }
- samples = exp_output;
- }
-
- unsigned stop_count = gradient->childCount();
- bool is_continuation = false;
- // Check if this sampled function is the continuation of the previous one
- if ( stop_count > 0 ) {
- // Get previous stop
- Inkscape::XML::Node *prev_stop = gradient->nthChild(stop_count-1);
- // Read its properties
- double prev_offset;
- sp_repr_get_double(prev_stop, "offset", &prev_offset);
- SPCSSAttr *css = sp_repr_css_attr(prev_stop, "style");
- guint32 prev_stop_color = sp_svg_read_color(sp_repr_css_property(css, "stop-color", NULL), 0);
- sp_repr_css_attr_unref(css);
- // Convert colors
- double r = SP_RGBA32_R_F (prev_stop_color);
- double g = SP_RGBA32_G_F (prev_stop_color);
- double b = SP_RGBA32_B_F (prev_stop_color);
- if ( fabs(prev_offset - offset0) < EPSILON &&
- fabs(samples[0] - r) < EPSILON &&
- fabs(samples[1] - g) < EPSILON &&
- fabs(samples[2] - b) < EPSILON ) {
-
- is_continuation = true;
- }
- }
+/**
+ * \brief Adds a stop with the given properties to the gradient's representation
+ */
+void SvgBuilder::_addStopToGradient(Inkscape::XML::Node *gradient, double offset,
+ GfxRGB *color, double opacity) {
+ Inkscape::XML::Node *stop = _xml_doc->createElement("svg:stop");
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ Inkscape::CSSOStringStream os_opacity;
+ os_opacity << opacity;
+ sp_repr_css_set_property(css, "stop-opacity", os_opacity.str().c_str());
+ gchar *color_text = svgConvertGfxRGB(color);
+ sp_repr_css_set_property(css, "stop-color", color_text);
- int num_stops_added;
- int i;
- if (is_continuation) {
- num_stops_added = 1;
- i = num_comps;
- } else {
- num_stops_added = i = 0;
- }
- while ( num_stops_added < 2 ) {
- Inkscape::XML::Node *stop = _xml_doc->createElement("svg:stop");
- SPCSSAttr *css = sp_repr_css_attr_new();
- Inkscape::CSSOStringStream os_opacity;
- os_opacity << opacity;
- gchar c[64];
- if ( num_comps == 1 ) {
- sp_svg_write_color(c, 64, SP_RGBA32_F_COMPOSE (samples[i], samples[i], samples[i], 1.0));
- } else {
- sp_svg_write_color(c, 64, SP_RGBA32_F_COMPOSE (samples[i], samples[i+1], samples[i+2], 1.0));
- }
- sp_repr_css_set_property(css, "stop-opacity", os_opacity.str().c_str());
- sp_repr_css_set_property(css, "stop-color", c);
+ sp_repr_css_change(stop, css, "style");
+ sp_repr_css_attr_unref(css);
+ sp_repr_set_css_double(stop, "offset", offset);
- sp_repr_css_change(stop, css, "style");
- sp_repr_css_attr_unref(css);
- sp_repr_set_css_double(stop, "offset", ( i < num_comps ) ? offset0 : offset1);
+ gradient->appendChild(stop);
+ Inkscape::GC::release(stop);
+}
- gradient->appendChild(stop);
- Inkscape::GC::release(stop);
- i += num_comps; // Advance to the next sample
- num_stops_added++;
- }
- // Free the output of the exponential function
- if ( func->getType() == 2 ) {
- delete samples;
+static bool svgGetShadingColorRGB(GfxShading *shading, double offset, GfxRGB *result) {
+ GfxColorSpace *color_space = shading->getColorSpace();
+ GfxColor temp;
+ if ( shading->getType() == 2 ) { // Axial shading
+ ((GfxAxialShading*)shading)->getColor(offset, &temp);
+ } else if ( shading->getType() == 3 ) { // Radial shading
+ ((GfxRadialShading*)shading)->getColor(offset, &temp);
+ } else {
+ return false;
}
-
+ // Convert it to RGB
+ color_space->getRGB(&temp, result);
+
return true;
}
-bool SvgBuilder::_addStopsToGradient(Inkscape::XML::Node *gradient, Function *func,
- double opacity) {
-
+#define INT_EPSILON 8
+bool SvgBuilder::_addGradientStops(Inkscape::XML::Node *gradient, GfxShading *shading,
+ Function *func) {
int type = func->getType();
if ( type == 0 || type == 2 ) { // Sampled or exponential function
- _addSamplesToGradient(gradient, func, 0.0, 1.0, opacity);
+ GfxRGB stop1, stop2;
+ if ( !svgGetShadingColorRGB(shading, 0.0, &stop1) ||
+ !svgGetShadingColorRGB(shading, 1.0, &stop2) ) {
+ return false;
+ } else {
+ _addStopToGradient(gradient, 0.0, &stop1, 1.0);
+ _addStopToGradient(gradient, 1.0, &stop2, 1.0);
+ }
} else if ( type == 3 ) { // Stitching
StitchingFunction *stitchingFunc = (StitchingFunction*)func;
double *bounds = stitchingFunc->getBounds();
int num_funcs = stitchingFunc->getNumFuncs();
- // Add samples from all the stitched functions
+ // Add stops from all the stitched functions
for ( int i = 0 ; i < num_funcs ; i++ ) {
- Function *func = stitchingFunc->getFunc(i);
- int func_type = func->getType();
- if ( func_type != 0 && func_type != 2 ) // Only sampled and exponential functions are supported
- continue;
-
- _addSamplesToGradient(gradient, func, bounds[i], bounds[i+1], opacity);
+ GfxRGB color;
+ svgGetShadingColorRGB(shading, bounds[i], &color);
+ bool is_continuation = false;
+ if ( i > 0 ) { // Compare to previous stop
+ GfxRGB prev_color;
+ svgGetShadingColorRGB(shading, bounds[i-1], &prev_color);
+ if ( abs(color.r - prev_color.r) < INT_EPSILON &&
+ abs(color.g - prev_color.g) < INT_EPSILON &&
+ abs(color.b - prev_color.b) < INT_EPSILON ) {
+ is_continuation = true;
+ }
+ }
+ // Add stops
+ if ( !is_continuation ) {
+ _addStopToGradient(gradient, bounds[i], &color, 1.0);
+ }
+ if ( is_continuation || ( i == num_funcs - 1 ) ) {
+ GfxRGB next_color;
+ svgGetShadingColorRGB(shading, bounds[i+1], &next_color);
+ _addStopToGradient(gradient, bounds[i+1], &next_color, 1.0);
+ }
}
} else { // Unsupported function type
return false;
diff --git a/src/extension/internal/pdfinput/svg-builder.h b/src/extension/internal/pdfinput/svg-builder.h
index f2fc779710148f71038d892ec9ed2db84305d58c..6a5d94ee26b8d87db8bc7410dc7752e73f4f2d41 100644 (file)
class GooString;
class Function;
struct GfxState;
+class GfxRGB;
class GfxPath;
class GfxPattern;
class GfxTilingPattern;
// Pattern creation
gchar *_createPattern(GfxPattern *pattern, GfxState *state, bool is_stroke=false);
- gchar *_createGradient(GfxShading *shading, double *matrix);
- bool _addStopsToGradient(Inkscape::XML::Node *gradient, Function *func, double opacity);
- bool _addSamplesToGradient(Inkscape::XML::Node *gradient, Function *func,
- double offset0, double offset1, double opacity);
+ gchar *_createGradient(GfxShading *shading, double *matrix, bool for_shading=false);
+ void _addStopToGradient(Inkscape::XML::Node *gradient, double offset,
+ GfxRGB *color, double opacity);
+ bool _addGradientStops(Inkscape::XML::Node *gradient, GfxShading *shading,
+ Function *func);
gchar *_createTilingPattern(GfxTilingPattern *tiling_pattern, GfxState *state,
bool is_stroke=false);
// Image/mask creation