summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 88396c9)
raw | patch | inline | side by side (parent: 88396c9)
author | miklosh <miklosh@users.sourceforge.net> | |
Thu, 9 Aug 2007 13:04:00 +0000 (13:04 +0000) | ||
committer | miklosh <miklosh@users.sourceforge.net> | |
Thu, 9 Aug 2007 13:04:00 +0000 (13:04 +0000) |
diff --git a/src/extension/internal/pdfinput/pdf-parser.cpp b/src/extension/internal/pdfinput/pdf-parser.cpp
index 1d312c1165004da7c3d6e0b224ae61007afef9fe..465350b78edcc7775c7dbaabc58f85d2c3fd36a5 100644 (file)
@@ -298,6 +298,7 @@ PdfParser::PdfParser(XRef *xrefA, Inkscape::Extension::Internal::SvgBuilder *bui
state = new GfxState(72.0, 72.0, cropBox, rotate, gTrue);
fontChanged = gFalse;
clip = clipNone;
+ lastClipPath = NULL;
ignoreUndef = 0;
operatorHistory = NULL;
builder = builderA;
@@ -353,6 +354,7 @@ PdfParser::PdfParser(XRef *xrefA, Inkscape::Extension::Internal::SvgBuilder *bui
state = new GfxState(72, 72, box, 0, gFalse);
fontChanged = gFalse;
clip = clipNone;
+ lastClipPath = NULL;
ignoreUndef = 0;
for (i = 0; i < 6; ++i) {
baseMatrix[i] = state->getCTM()[i];
if (state) {
delete state;
}
+ if (lastClipPath) {
+ delete lastClipPath;
+ }
}
void PdfParser::parse(Object *obj, GBool topLevel) {
GfxShading *shading;
GfxPath *savedPath;
double xMin, yMin, xMax, yMax;
+ double gradientTransform[6];
+ double *matrix = NULL;
+ GBool savedState = gFalse;
if (!(shading = res->lookupShading(args[0].getName()))) {
return;
}
// save current graphics state
- savedPath = state->getPath()->copy();
- saveState();
+ if (shading->getType() != 2 && shading->getType() != 3) {
+ savedPath = state->getPath()->copy();
+ saveState();
+ savedState = gTrue;
+ } else { // get gradient transform if possible
+ // check proper operator sequence
+ // first there should be one W(*) and then one 'cm' somewhere before 'sh'
+ GBool seenClip, seenConcat;
+ seenClip = gFalse;
+ seenConcat = gFalse;
+ int i = 1;
+ while (i <= maxOperatorHistoryDepth) {
+ const char *opName = getPreviousOperator(i);
+ if (!strcmp(opName, "cm")) {
+ if (seenConcat) { // more than one 'cm'
+ break;
+ } else {
+ seenConcat = gTrue;
+ }
+ } else if (!strcmp(opName, "W") || !strcmp(opName, "W*")) {
+ if (seenConcat) { // good sequence
+ seenClip = gTrue;
+ break;
+ } else { // no 'cm' so bail out
+ break;
+ }
+ }
+ i++;
+ }
+
+ if (seenConcat && seenClip) {
+ if (builder->getTransform((double*)&gradientTransform)) {
+ matrix = (double*)&gradientTransform;
+ builder->setTransform(1.0, 0.0, 0.0, 1.0, 0.0, 0.0); // remove transform
+ }
+ }
+ }
// clip to bbox
if (shading->getHasBBox()) {
state->lineTo(xMin, yMax);
state->closePath();
state->clip();
- builder->clip(state);
+ if (savedState)
+ builder->setClipPath(state);
+ else
+ builder->clip(state);
state->clearPath();
}
// set the color space
- state->setFillColorSpace(shading->getColorSpace()->copy());
+ if (savedState)
+ state->setFillColorSpace(shading->getColorSpace()->copy());
// do shading type-specific operations
switch (shading->getType()) {
break;
case 2:
case 3:
- // no need to implement these
+ if (lastClipPath) {
+ builder->addShadedFill(shading, matrix, lastClipPath,
+ lastClipType == clipEO ? true : false);
+ }
break;
case 4:
case 5:
}
// restore graphics state
- restoreState();
- state->setPath(savedPath);
+ if (savedState) {
+ restoreState();
+ state->setPath(savedPath);
+ }
delete shading;
}
void PdfParser::opClip(Object args[], int numArgs) {
clip = clipNormal;
+ lastClipType = clipNormal;
+ if (lastClipPath)
+ delete lastClipPath;
+ lastClipPath = state->getPath()->copy();
}
void PdfParser::opEOClip(Object args[], int numArgs) {
clip = clipEO;
+ lastClipType = clipEO;
+ if (lastClipPath)
+ delete lastClipPath;
+ lastClipPath = state->getPath()->copy();
}
//------------------------------------------------------------------------
diff --git a/src/extension/internal/pdfinput/pdf-parser.h b/src/extension/internal/pdfinput/pdf-parser.h
index 5747dcc9a0acd95b6974f726790096fd480d7c8f..40457453729ba14af273071ce0ff87ecb78f34b1 100644 (file)
void pushOperator(const char *name);
OpHistoryEntry *popOperator();
const char *getPreviousOperator(unsigned int look_back=1); // returns the nth previous operator's name
+ GfxPath *lastClipPath; // Used as the path to be filled for an 'sh' operator
+ GfxClipType lastClipType;
void go(GBool topLevel);
void execOp(Object *cmd, Object args[], int numArgs);
diff --git a/src/extension/internal/pdfinput/svg-builder.cpp b/src/extension/internal/pdfinput/svg-builder.cpp
index 78426b85da3052db7a0afc5cfca0f853541cf6cb..08719afd023f500ca7201987b8b6e6abd87977cb 100644 (file)
@@ -382,6 +382,42 @@ void SvgBuilder::addPath(GfxState *state, bool fill, bool stroke, bool even_odd)
Inkscape::GC::release(path);
}
+/**
+ * \brief Emits the current path in poppler's GfxState data structure
+ * The path is set to be filled with the given shading.
+ */
+void SvgBuilder::addShadedFill(GfxShading *shading, double *matrix, GfxPath *path,
+ bool even_odd) {
+
+ Inkscape::XML::Node *path_node = _xml_doc->createElement("svg:path");
+ gchar *pathtext = svgInterpretPath(path);
+ path_node->setAttribute("d", pathtext);
+ g_free(pathtext);
+
+ // Set style
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ gchar *id = _createGradient(shading, matrix);
+ if (id) {
+ gchar *urltext = g_strdup_printf ("url(#%s)", id);
+ sp_repr_css_set_property(css, "fill", urltext);
+ g_free(urltext);
+ g_free(id);
+ } else {
+ sp_repr_css_attr_unref(css);
+ Inkscape::GC::release(path_node);
+ return;
+ }
+ if (even_odd) {
+ sp_repr_css_set_property(css, "fill-rule", "evenodd");
+ }
+ sp_repr_css_set_property(css, "stroke", "none");
+ sp_repr_css_change(path_node, css, "style");
+ sp_repr_css_attr_unref(css);
+
+ _container->appendChild(path_node);
+ Inkscape::GC::release(path_node);
+}
+
/**
* \brief Clips to the current path set in GfxState
* \param state poppler's data structure
@@ -480,7 +516,9 @@ gchar *SvgBuilder::_createPattern(GfxPattern *pattern, GfxState *state, bool is_
gchar *id = NULL;
if ( pattern != NULL ) {
if ( pattern->getType() == 2 ) { // Shading pattern
- id = _createGradient((GfxShadingPattern*)pattern);
+ GfxShadingPattern *shading_pattern = (GfxShadingPattern*)pattern;
+ id = _createGradient(shading_pattern->getShading(),
+ shading_pattern->getMatrix());
} else if ( pattern->getType() == 1 ) { // Tiling pattern
id = _createTilingPattern((GfxTilingPattern*)pattern, state, is_stroke);
}
* \brief Creates a linear or radial gradient from poppler's data structure
* \return id of the created object
*/
-gchar *SvgBuilder::_createGradient(GfxShadingPattern *shading_pattern) {
- GfxShading *shading = shading_pattern->getShading();
+gchar *SvgBuilder::_createGradient(GfxShading *shading, double *matrix) {
Inkscape::XML::Node *gradient;
Function *func;
int num_funcs;
}
gradient->setAttribute("gradientUnits", "userSpaceOnUse");
// Flip the gradient transform around the y axis
- double *p2u = shading_pattern->getMatrix();
- NR::Matrix pat_matrix(p2u[0], p2u[1], p2u[2], p2u[3], p2u[4], p2u[5]);
- 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);
+ 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;
+ gchar *transform_text = sp_svg_transform_write(pat_matrix);
+ gradient->setAttribute("gradientTransform", transform_text);
+ g_free(transform_text);
+ }
if ( extend0 && extend1 ) {
gradient->setAttribute("spreadMethod", "pad");
diff --git a/src/extension/internal/pdfinput/svg-builder.h b/src/extension/internal/pdfinput/svg-builder.h
index 5004e90f9af2c358bc8798ae6b9baccaa8f73ac4..f2fc779710148f71038d892ec9ed2db84305d58c 100644 (file)
class GooString;
class Function;
struct GfxState;
+class GfxPath;
class GfxPattern;
-class GfxShadingPattern;
class GfxTilingPattern;
+class GfxShading;
class GfxFont;
class GfxImageColorMap;
class Stream;
// Path adding
void addPath(GfxState *state, bool fill, bool stroke, bool even_odd=false);
+ void addShadedFill(GfxShading *shading, double *matrix, GfxPath *path, bool even_odd=false);
// Image handling
void addImage(GfxState *state, Stream *str, int width, int height,
// Pattern creation
gchar *_createPattern(GfxPattern *pattern, GfxState *state, bool is_stroke=false);
- gchar *_createGradient(GfxShadingPattern *shading_pattern);
+ 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);