diff options
| author | Krzysztof Kosi??ski <tweenk.pl@gmail.com> | 2015-05-22 07:02:44 +0000 |
|---|---|---|
| committer | Krzysztof KosiĆski <tweenk.pl@gmail.com> | 2015-05-22 07:02:44 +0000 |
| commit | 35d94a8e1c01cd60e4fcf4c15f46fee38c765fca (patch) | |
| tree | d8366acd729a6a9d4bdc1001f050a43f30d8b7ad /src | |
| parent | Undo changes to CMakeLists.txt in 2geom directory after syncs (diff) | |
| parent | minor tweaks to libUEMF and related code (diff) | |
| download | inkscape-35d94a8e1c01cd60e4fcf4c15f46fee38c765fca.tar.gz inkscape-35d94a8e1c01cd60e4fcf4c15f46fee38c765fca.zip | |
Merge from trunk
(bzr r14059.2.15)
Diffstat (limited to 'src')
107 files changed, 6396 insertions, 5340 deletions
diff --git a/src/2geom/sbasis-to-bezier.cpp b/src/2geom/sbasis-to-bezier.cpp index fe7bbc91c..dfd07d84c 100644 --- a/src/2geom/sbasis-to-bezier.cpp +++ b/src/2geom/sbasis-to-bezier.cpp @@ -239,6 +239,8 @@ void sbasis_to_cubic_bezier (std::vector<Point> & bz, D2<SBasis> const& sb) midx = 8*midx - 4*bz[0][X] - 4*bz[3][X]; // re-define relative to center midy = 8*midy - 4*bz[0][Y] - 4*bz[3][Y]; + if ((std::abs(midx) < EPSILON) && (std::abs(midy) < EPSILON)) + return; if ((std::abs(xprime[0]) < EPSILON) && (std::abs(yprime[0]) < EPSILON) && ((std::abs(xprime[1]) > EPSILON) || (std::abs(yprime[1]) > EPSILON))) { // degenerate handle at 0 : use distance of closest approach @@ -258,11 +260,15 @@ void sbasis_to_cubic_bezier (std::vector<Point> & bz, D2<SBasis> const& sb) dely[1] = 0; } else if (std::abs(xprime[1]*yprime[0] - yprime[1]*xprime[0]) > // general case : fit mid fxn value 0.002 * std::abs(xprime[1]*xprime[0] + yprime[1]*yprime[0])) { // approx. 0.1 degree of angle - denom = 3.0*(xprime[1]*yprime[0] - yprime[1]*xprime[0]); + double test1 = (bz[1][Y] - bz[0][Y])*(bz[3][X] - bz[0][X]) - (bz[1][X] - bz[0][X])*(bz[3][Y] - bz[0][Y]); + double test2 = (bz[2][Y] - bz[0][Y])*(bz[3][X] - bz[0][X]) - (bz[2][X] - bz[0][X])*(bz[3][Y] - bz[0][Y]); + if (test1*test2 < 0) // reject anti-symmetric case, LP Bug 1428267 & Bug 1428683 + return; + denom = xprime[1]*yprime[0] - yprime[1]*xprime[0]; for (int i = 0; i < 2; ++i) { numer = xprime[1 - i]*midy - yprime[1 - i]*midx; - delx[i] = xprime[i]*numer/denom; - dely[i] = yprime[i]*numer/denom; + delx[i] = xprime[i]*numer/denom/3; + dely[i] = yprime[i]*numer/denom/3; } } else if ((xprime[0]*xprime[1] < 0) || (yprime[0]*yprime[1] < 0)) { // symmetric case : use distance of closest approach numer = midx*xprime[0] + midy*yprime[0]; @@ -509,10 +515,10 @@ path_from_sbasis(D2<SBasis> const &B, double tol, bool only_cubicbeziers) { TODO: some of this logic should be lifted into svg-path */ PathVector -path_from_piecewise(Geom::Piecewise<Geom::D2<Geom::SBasis> > const &B, double tol, bool only_cubicbeziers) { - Geom::PathBuilder pb; +path_from_piecewise(Piecewise<D2<SBasis> > const &B, double tol, bool only_cubicbeziers) { + PathBuilder pb; if(B.size() == 0) return pb.peek(); - Geom::Point start = B[0].at0(); + Point start = B[0].at0(); pb.moveTo(start); for(unsigned i = 0; ; i++) { if ( (i+1 == B.size()) diff --git a/src/attributes-test.h b/src/attributes-test.h index 7379e4e85..411304ec3 100644 --- a/src/attributes-test.h +++ b/src/attributes-test.h @@ -40,6 +40,10 @@ public: I've added these manually. SVG 2: white-space, shape-inside, shape-outside, shape-padding, shape-margin + SVG 2: text-decoration-fill, text-decoration-stroke + SVG 2: solid-color, solid-opacity + SVG 2: Hatches and Meshes + CSS 3: font-variant-xxx, font-feature-settings */ struct {char const *attr; bool supported;} const all_attrs[] = { {"attributeName", true}, @@ -124,11 +128,18 @@ struct {char const *attr; bool supported;} const all_attrs[] = { {"flood-color", true}, {"flood-opacity", true}, {"font-family", true}, + {"font-feature-settings", true}, {"font-size", true}, {"font-size-adjust", true}, {"font-stretch", true}, {"font-style", true}, {"font-variant", true}, + {"font-variant-ligatures", true}, + {"font-variant-position", true}, + {"font-variant-caps", true}, + {"font-variant-numeric", true}, + {"font-variant-east-asian", true}, + {"font-variant-alternates", true}, {"font-weight", true}, {"format", false}, {"from", true}, @@ -288,6 +299,8 @@ struct {char const *attr; bool supported;} const all_attrs[] = { {"text-decoration-line", true}, {"text-decoration-style", true}, {"text-decoration-color", true}, + {"text-decoration-fill", true}, + {"text-decoration-stroke", true}, {"text-indent", true}, {"text-rendering", true}, {"text-transform", true}, @@ -381,8 +394,11 @@ struct {char const *attr; bool supported;} const all_attrs[] = { {"inkscape:pageopacity", true}, {"inkscape:pageshadow", true}, {"inkscape:path-effect", true}, + // SPItem {"inkscape:transform-center-x", true}, {"inkscape:transform-center-y", true}, + {"inkscape:highlight-color", true}, + // Namedview {"inkscape:zoom", true}, {"inkscape:cx", true}, {"inkscape:cy", true}, @@ -392,6 +408,7 @@ struct {char const *attr; bool supported;} const all_attrs[] = { {"inkscape:window-y", true}, {"inkscape:window-maximized", true}, {"inkscape:current-layer", true}, + // Connector tool {"inkscape:connector-type", true}, {"inkscape:connection-start", true}, {"inkscape:connection-end", true}, @@ -401,10 +418,12 @@ struct {char const *attr; bool supported;} const all_attrs[] = { {"inkscape:connector-curvature", true}, {"inkscape:connector-avoid", true}, {"inkscape:connector-spacing", true}, + // Ellipse, Spiral, Star {"sodipodi:cx", true}, {"sodipodi:cy", true}, {"sodipodi:rx", true}, {"sodipodi:ry", true}, + // Box tool {"inkscape:perspectiveID", true}, {"inkscape:corner0", true}, {"inkscape:corner7", true}, @@ -414,6 +433,7 @@ struct {char const *attr; bool supported;} const all_attrs[] = { {"inkscape:vp_y", true}, {"inkscape:vp_z", true}, {"inkscape:persp3d-origin", true}, + // Star tool {"sodipodi:start", true}, {"sodipodi:end", true}, {"sodipodi:open", true}, @@ -446,9 +466,19 @@ struct {char const *attr; bool supported;} const all_attrs[] = { {"inkscape:layoutOptions", true}, {"osb:paint", true}, + /* SPSolidColor" */ + {"solid-color", true}, + {"solid-opacity", true}, + /* SPMeshPatch */ {"tensor", true}, + /* SPHash */ + {"hatchUnits", true}, + {"hatchContentUnits", true}, + {"hatchTransform", true}, + {"pitch", true}, + /* SPNamedView */ {"fit-margin-top", true}, {"fit-margin-left", true}, @@ -485,8 +515,10 @@ struct {char const *attr; bool supported;} const all_attrs[] = { {"pagecolor", true}, /* SPGuide */ - {"position", true} + {"position", true}, + /* SPTag */ + {"inkscape:expanded", true} }; diff --git a/src/desktop-style.cpp b/src/desktop-style.cpp index afdc3064a..d2109c03c 100644 --- a/src/desktop-style.cpp +++ b/src/desktop-style.cpp @@ -576,8 +576,8 @@ objects_query_fillstroke (const std::vector<SPItem*> &objects, SPStyle *style_re return QUERY_STYLE_MULTIPLE_DIFFERENT; // different kind of server } - SPPattern *pat = pattern_getroot (pattern); - SPPattern *pat_res = pattern_getroot (pattern_res); + SPPattern *pat = SP_PATTERN (server)->rootPattern(); + SPPattern *pat_res = SP_PATTERN (server_res)->rootPattern(); if (pat_res != pat) { return QUERY_STYLE_MULTIPLE_DIFFERENT; // different pattern roots } @@ -1168,6 +1168,94 @@ objects_query_fontstyle (const std::vector<SPItem*> &objects, SPStyle *style_res } } +int +objects_query_fontvariants (const std::vector<SPItem*> &objects, SPStyle *style_res) +{ + bool set = false; + + int texts = 0; + + SPILigatures* ligatures_res = &(style_res->font_variant_ligatures); + SPIEnum* position_res = &(style_res->font_variant_position); + SPIEnum* caps_res = &(style_res->font_variant_caps); + SPINumeric* numeric_res = &(style_res->font_variant_numeric); + + // Stores 'and' of all values + ligatures_res->computed = SP_CSS_FONT_VARIANT_LIGATURES_NORMAL; + position_res->computed = SP_CSS_FONT_VARIANT_POSITION_NORMAL; + caps_res->computed = SP_CSS_FONT_VARIANT_CAPS_NORMAL; + numeric_res->computed = SP_CSS_FONT_VARIANT_NUMERIC_NORMAL; + + // Stores only differences + ligatures_res->value = 0; + position_res->value = 0; + caps_res->value = 0; + numeric_res->value = 0; + + for (std::vector<SPItem*>::const_iterator i = objects.begin(); i != objects.end(); i++) { + SPObject *obj = *i; + + if (!isTextualItem(obj)) { + continue; + } + + SPStyle *style = obj->style; + if (!style) { + continue; + } + + texts ++; + + SPILigatures* ligatures_in = &(style->font_variant_ligatures); + SPIEnum* position_in = &(style->font_variant_position); + SPIEnum* caps_in = &(style->font_variant_caps); + SPINumeric* numeric_in = &(style->font_variant_numeric); + // computed stores which bits are on/off, only valid if same between all selected objects. + // value stores which bits are different between objects. This is a bit of an abuse of + // the values but then we don't need to add new variables to class. + if (set) { + ligatures_res->value |= (ligatures_res->computed ^ ligatures_in->computed ); + ligatures_res->computed &= ligatures_in->computed; + + position_res->value |= (position_res->computed ^ position_in->computed ); + position_res->computed &= position_in->computed; + + caps_res->value |= (caps_res->computed ^ caps_in->computed ); + caps_res->computed &= caps_in->computed; + + numeric_res->value |= (numeric_res->computed ^ numeric_in->computed ); + numeric_res->computed &= numeric_in->computed; + + } else { + ligatures_res->computed = ligatures_in->computed; + position_res->computed = position_in->computed; + caps_res->computed = caps_in->computed; + numeric_res->computed = numeric_in->computed; + } + + set = true; + } + + bool different = (style_res->font_variant_ligatures.value != 0 || + style_res->font_variant_position.value != 0 || + style_res->font_variant_caps.value != 0 || + style_res->font_variant_numeric.value != 0 ); + + if (texts == 0 || !set) + return QUERY_STYLE_NOTHING; + + if (texts > 1) { + if (different) { + return QUERY_STYLE_MULTIPLE_DIFFERENT; + } else { + return QUERY_STYLE_MULTIPLE_SAME; + } + } else { + return QUERY_STYLE_SINGLE; + } +} + + /** * Write to style_res the baseline numbers. */ @@ -1577,6 +1665,8 @@ sp_desktop_query_style_from_list (const std::vector<SPItem*> &list, SPStyle *sty return objects_query_fontfamily (list, style); } else if (property == QUERY_STYLE_PROPERTY_FONTSTYLE) { return objects_query_fontstyle (list, style); + } else if (property == QUERY_STYLE_PROPERTY_FONTVARIANTS) { + return objects_query_fontvariants (list, style); } else if (property == QUERY_STYLE_PROPERTY_FONTNUMBERS) { return objects_query_fontnumbers (list, style); } else if (property == QUERY_STYLE_PROPERTY_BASELINES) { @@ -1598,6 +1688,7 @@ sp_desktop_query_style_from_list (const std::vector<SPItem*> &list, SPStyle *sty int sp_desktop_query_style(SPDesktop *desktop, SPStyle *style, int property) { + // Used by text tool and in gradient dragging int ret = desktop->_query_style_signal.emit(style, property); if (ret != QUERY_STYLE_NOTHING) diff --git a/src/desktop-style.h b/src/desktop-style.h index a72f49776..e5fe50440 100644 --- a/src/desktop-style.h +++ b/src/desktop-style.h @@ -47,6 +47,7 @@ enum { // which property was queried (add when you need more) QUERY_STYLE_PROPERTY_FONT_SPECIFICATION, //-inkscape-font-specification QUERY_STYLE_PROPERTY_FONTFAMILY, // font-family QUERY_STYLE_PROPERTY_FONTSTYLE, // font style + QUERY_STYLE_PROPERTY_FONTVARIANTS, // font variants (OpenType features) QUERY_STYLE_PROPERTY_FONTNUMBERS, // size, spacings QUERY_STYLE_PROPERTY_BASELINES, // baseline-shift QUERY_STYLE_PROPERTY_MASTEROPACITY, // opacity @@ -71,6 +72,7 @@ int objects_query_fillstroke (const std::vector<SPItem*> &objects, SPStyle *styl int objects_query_fontnumbers (const std::vector<SPItem*> &objects, SPStyle *style_res); int objects_query_fontstyle (const std::vector<SPItem*> &objects, SPStyle *style_res); int objects_query_fontfamily (const std::vector<SPItem*> &objects, SPStyle *style_res); +int objects_query_fontvariants (const std::vector<SPItem*> &objects, SPStyle *style_res); int objects_query_opacity (const std::vector<SPItem*> &objects, SPStyle *style_res); int objects_query_strokewidth (const std::vector<SPItem*> &objects, SPStyle *style_res); int objects_query_miterlimit (const std::vector<SPItem*> &objects, SPStyle *style_res); diff --git a/src/display/drawing-text.cpp b/src/display/drawing-text.cpp index e20a7ff2a..3928ad796 100644 --- a/src/display/drawing-text.cpp +++ b/src/display/drawing-text.cpp @@ -367,7 +367,7 @@ void DrawingText::decorateStyle(DrawingContext &dc, double vextent, double xphas /* returns scaled line thickness */ void DrawingText::decorateItem(DrawingContext &dc, double phase_length, bool under) { - if (_nrstyle.font_size < 1.0e-32)return; // would cause a divide by zero and nothing would be visible anyway + if ( _nrstyle.font_size <= 1.0e-32 )return; // might cause a divide by zero or overflow and nothing would be visible anyway double tsp_width_adj = _nrstyle.tspan_width / _nrstyle.font_size; double tsp_asc_adj = _nrstyle.ascender / _nrstyle.font_size; double tsp_size_adj = (_nrstyle.ascender + _nrstyle.descender) / _nrstyle.font_size; @@ -381,6 +381,7 @@ void DrawingText::decorateItem(DrawingContext &dc, double phase_length, bool und Geom::Point p2; // All lines must be the same thickness, in combinations, line_through trumps underline double thickness = final_underline_thickness; + if ( thickness <= 1.0e-32 )return; // might cause a divide by zero or overflow and nothing would be visible anyway dc.setTolerance(0.5); // Is this really necessary... could effect dots. if( under ) { diff --git a/src/extension/CMakeLists.txt b/src/extension/CMakeLists.txt index d1104f3cc..21e652563 100644 --- a/src/extension/CMakeLists.txt +++ b/src/extension/CMakeLists.txt @@ -36,7 +36,6 @@ set(extension_SRC internal/cairo-render-context.cpp internal/cairo-renderer.cpp internal/cairo-renderer-pdf-out.cpp - internal/cdr-input.cpp internal/emf-inout.cpp internal/emf-print.cpp internal/gdkpixbuf-input.cpp @@ -54,10 +53,8 @@ set(extension_SRC internal/svg.cpp internal/svgz.cpp internal/text_reassemble.c - internal/vsd-input.cpp internal/wmf-inout.cpp internal/wmf-print.cpp - internal/wpg-input.cpp internal/filter/filter-all.cpp internal/filter/filter-file.cpp @@ -104,7 +101,6 @@ set(extension_SRC internal/cairo-render-context.h internal/cairo-renderer-pdf-out.h internal/cairo-renderer.h - internal/cdr-input.h internal/clear-n_.h internal/emf-inout.h internal/emf-print.h @@ -140,10 +136,8 @@ set(extension_SRC internal/svg.h internal/svgz.h internal/text_reassemble.h - internal/vsd-input.h internal/wmf-inout.h internal/wmf-print.h - internal/wpg-input.h ) if(WIN32) @@ -151,6 +145,20 @@ if(WIN32) ) endif() +if(WITH_LIBCDR) + list(APPEND extension_SRC + internal/cdr-input.cpp + internal/cdr-input.h + ) +endif() + +if(WITH_LIBVISIO) + list(APPEND extension_SRC + internal/vsd-input.cpp + internal/vsd-input.h + ) +endif() + if(WITH_LIBWPG) list(APPEND extension_SRC internal/wpg-input.cpp @@ -158,7 +166,7 @@ if(WITH_LIBWPG) ) endif() -if(ImageMagick_FOUND) +if(WITH_IMAGE_MAGICK) list(APPEND extension_SRC internal/bitmap/adaptiveThreshold.cpp internal/bitmap/adaptiveThreshold.h diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp index 27e34dbcf..c3e416184 100644 --- a/src/extension/internal/cairo-render-context.cpp +++ b/src/extension/internal/cairo-render-context.cpp @@ -1008,17 +1008,16 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver ps2user = Geom::identity(); pcs2dev = Geom::identity(); - double x = pattern_x(pat); - double y = pattern_y(pat); - double width = pattern_width(pat); - double height = pattern_height(pat); + double x = pat->x(); + double y = pat->y(); + double width = pat->width(); + double height = pat->height(); double bbox_width_scaler; double bbox_height_scaler; TRACE(("%f x %f pattern\n", width, height)); - if (pbox && pattern_patternUnits(pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) { - //Geom::Affine bbox2user (pbox->x1 - pbox->x0, 0.0, 0.0, pbox->y1 - pbox->y0, pbox->x0, pbox->y0); + if (pbox && pat->patternUnits() == SPPattern::UNITS_OBJECTBOUNDINGBOX) { bbox_width_scaler = pbox->width(); bbox_height_scaler = pbox->height(); ps2user[4] = x * bbox_width_scaler + pbox->left(); @@ -1031,13 +1030,13 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver } // apply pattern transformation - Geom::Affine pattern_transform(pattern_patternTransform(pat)); + Geom::Affine pattern_transform(pat->getTransform()); ps2user *= pattern_transform; Geom::Point ori (ps2user[4], ps2user[5]); // create pattern contents coordinate system if (pat->viewBox_set) { - Geom::Rect view_box = *pattern_viewBox(pat); + Geom::Rect view_box = *pat->viewbox(); double x, y, w, h; x = 0; @@ -1050,7 +1049,7 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver pcs2dev[3] = h / view_box.height(); pcs2dev[4] = x - view_box.left() * pcs2dev[0]; pcs2dev[5] = y - view_box.top() * pcs2dev[3]; - } else if (pbox && pattern_patternContentUnits(pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) { + } else if (pbox && pat->patternContentUnits() == SPPattern::UNITS_OBJECTBOUNDINGBOX) { pcs2dev[0] = pbox->width(); pcs2dev[3] = pbox->height(); } diff --git a/src/extension/internal/emf-print.cpp b/src/extension/internal/emf-print.cpp index 7c514d6e7..5b8aae655 100644 --- a/src/extension/internal/emf-print.cpp +++ b/src/extension/internal/emf-print.cpp @@ -388,8 +388,8 @@ int PrintEmf::create_brush(SPStyle const *style, PU_COLORREF fcolor) } else if (SP_IS_PATTERN(SP_STYLE_FILL_SERVER(style))) { // must be paint-server SPPaintServer *paintserver = style->fill.value.href->getObject(); SPPattern *pat = SP_PATTERN(paintserver); - double dwidth = pattern_width(pat); - double dheight = pattern_height(pat); + double dwidth = pat->width(); + double dheight = pat->height(); width = dwidth; height = dheight; brush_classify(pat, 0, &pixbuf, &hatchType, &hatchColor, &bkColor); @@ -573,8 +573,8 @@ int PrintEmf::create_pen(SPStyle const *style, const Geom::Affine &transform) if (SP_IS_PATTERN(SP_STYLE_STROKE_SERVER(style))) { // must be paint-server SPPaintServer *paintserver = style->stroke.value.href->getObject(); SPPattern *pat = SP_PATTERN(paintserver); - double dwidth = pattern_width(pat); - double dheight = pattern_height(pat); + double dwidth = pat->width(); + double dheight = pat->height(); width = dwidth; height = dheight; brush_classify(pat, 0, &pixbuf, &hatchType, &hatchColor, &bkColor); diff --git a/src/extension/internal/filter/color.h b/src/extension/internal/filter/color.h index c3c26bf8b..b9c76615c 100644 --- a/src/extension/internal/filter/color.h +++ b/src/extension/internal/filter/color.h @@ -258,7 +258,7 @@ public: "<param name=\"type\" gui-text=\"" N_("Blindness type:") "\" type=\"enum\">\n" "<_item value=\"0.618 0.32 0.062 0 0 0.163 0.775 0.062 0 0 0.163 0.32 0.516 0 0 0 0 0 1 0 \">" N_("Rod monochromacy (atypical achromatopsia)") "</_item>\n" "<_item value=\"0.299 0.587 0.114 0 0 0.299 0.587 0.114 0 0 0.299 0.587 0.114 0 0 0 0 0 1 0 \">" N_("Cone monochromacy (typical achromatopsia)") "</_item>\n" - "<_item value=\"0.8 0.2 0 0 0 0.2583 0.74167 0 0 0 0 0.14167 0.85833 0 0 0 0 0 1 0 \">" N_("Geen weak (deuteranomaly)") "</_item>\n" + "<_item value=\"0.8 0.2 0 0 0 0.2583 0.74167 0 0 0 0 0.14167 0.85833 0 0 0 0 0 1 0 \">" N_("Green weak (deuteranomaly)") "</_item>\n" "<_item value=\"0.625 0.375 0 0 0 0.7 0.3 0 0 0 0 0.3 0.7 0 0 0 0 0 1 0 \">" N_("Green blind (deuteranopia)") "</_item>\n" "<_item value=\"0.8166 0.1833 0 0 0 0.333 0.666 0 0 0 0 0.125 0.875 0 0 0 0 0 1 0 \">" N_("Red weak (protanomaly)") "</_item>\n" "<_item value=\"0.566 0.43333 0 0 0 0.55833 0.4416 0 0 0 0 0.24167 0.75833 0 0 0 0 0 1 0 \">" N_("Red blind (protanopia)") "</_item>\n" diff --git a/src/extension/internal/text_reassemble.c b/src/extension/internal/text_reassemble.c index d3aafef12..fa983b83d 100644 --- a/src/extension/internal/text_reassemble.c +++ b/src/extension/internal/text_reassemble.c @@ -67,8 +67,8 @@ Optional compiler switches for development: File: text_reassemble.c -Version: 0.0.16 -Date: 25-FEB-2015 +Version: 0.0.17 +Date: 21-MAY-2015 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu Copyright: 2015 David Mathog and California Institute of Technology (Caltech) @@ -2204,10 +2204,10 @@ void TR_layout_2_svg(TR_INFO *tri){ sprintf(obuf,"text-decoration:"); /* multiple text decoration styles may be set */ utmp = tsp->decoration & TXTDECOR_TMASK; - if(utmp & TXTDECOR_UNDER ){ strcat(obuf,"underline"); } - if(utmp & TXTDECOR_OVER ){ strcat(obuf,"overline"); } - if(utmp & TXTDECOR_BLINK ){ strcat(obuf,"blink"); } - if(utmp & TXTDECOR_STRIKE){ strcat(obuf,"line-through");} + if(utmp & TXTDECOR_UNDER ){ strcat(obuf," underline"); } + if(utmp & TXTDECOR_OVER ){ strcat(obuf," overline"); } + if(utmp & TXTDECOR_BLINK ){ strcat(obuf," blink"); } + if(utmp & TXTDECOR_STRIKE){ strcat(obuf," line-through");} if(*obuf){ /* only a single text decoration line type may be set */ switch(tsp->decoration & TXTDECOR_LMASK){ diff --git a/src/extension/internal/wmf-inout.cpp b/src/extension/internal/wmf-inout.cpp index f76fa16b4..d17180d91 100644 --- a/src/extension/internal/wmf-inout.cpp +++ b/src/extension/internal/wmf-inout.cpp @@ -449,7 +449,8 @@ uint32_t Wmf::add_dib_image(PWMF_CALLBACK_DATA d, const char *dib, uint32_t iUsa char *rgba_px = NULL; // RGBA pixels const char *px = NULL; // DIB pixels const U_RGBQUAD *ct = NULL; // DIB color table - int32_t width, height, colortype, numCt, invert; // if needed these values will be set by wget_DIB_params + uint32_t numCt; + int32_t width, height, colortype, invert; // if needed these values will be set by wget_DIB_params if(iUsage == U_DIB_RGB_COLORS){ // next call returns pointers and values, but allocates no memory dibparams = wget_DIB_params(dib, &px, &ct, &numCt, &width, &height, &colortype, &invert); @@ -1318,7 +1319,8 @@ void Wmf::common_dib_to_image(PWMF_CALLBACK_DATA d, const char *dib, char *sub_px = NULL; // RGBA pixels, subarray const char *px = NULL; // DIB pixels const U_RGBQUAD *ct = NULL; // color table - int32_t width, height, colortype, numCt, invert; // if needed these values will be set in wget_DIB_params + uint32_t numCt; + int32_t width, height, colortype, invert; // if needed these values will be set in wget_DIB_params if(iUsage == U_DIB_RGB_COLORS){ // next call returns pointers and values, but allocates no memory dibparams = wget_DIB_params(dib, &px, &ct, &numCt, &width, &height, &colortype, &invert); diff --git a/src/extension/internal/wmf-print.cpp b/src/extension/internal/wmf-print.cpp index 127030832..271dec702 100644 --- a/src/extension/internal/wmf-print.cpp +++ b/src/extension/internal/wmf-print.cpp @@ -379,8 +379,8 @@ int PrintWmf::create_brush(SPStyle const *style, U_COLORREF *fcolor) } else if (SP_IS_PATTERN(SP_STYLE_FILL_SERVER(style))) { // must be paint-server SPPaintServer *paintserver = style->fill.value.href->getObject(); SPPattern *pat = SP_PATTERN(paintserver); - double dwidth = pattern_width(pat); - double dheight = pattern_height(pat); + double dwidth = pat->width(); + double dheight = pat->height(); width = dwidth; height = dheight; brush_classify(pat, 0, &pixbuf, &hatchType, &hatchColor, &bkColor); diff --git a/src/extension/param/color.cpp b/src/extension/param/color.cpp index b774bac83..3162e8a40 100644 --- a/src/extension/param/color.cpp +++ b/src/extension/param/color.cpp @@ -24,41 +24,37 @@ #include "color.h" #include <color.h> -#include "widgets/sp-color-selector.h" -#include "widgets/sp-color-notebook.h" +#include "ui/widget/color-notebook.h" #include "preferences.h" - namespace Inkscape { namespace Extension { -void sp_color_param_changed(SPColorSelector *csel, GObject *cp); - - ParamColor::~ParamColor(void) { - + _color_changed.disconnect(); } guint32 ParamColor::set( guint32 in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/ ) { - _value = in; + _color_changed.block(true); + _color.setValue(in); + _color_changed.block(false); gchar * prefname = this->pref_name(); std::string value; string(value); - + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setString(extension_pref_root + prefname, value); g_free(prefname); - return _value; + return in; } -ParamColor::ParamColor(const gchar *name, const gchar *guitext, const gchar *desc, const Parameter::_scope_t scope, - bool gui_hidden, const gchar *gui_tip, Inkscape::Extension::Extension *ext, - Inkscape::XML::Node *xml) - : Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext), _value(0), _changeSignal(0) +ParamColor::ParamColor (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) : + Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext), + _changeSignal(0) { const char * defaulthex = NULL; if (xml->firstChild() != NULL) @@ -72,51 +68,46 @@ ParamColor::ParamColor(const gchar *name, const gchar *guitext, const gchar *des if (!paramval.empty()) defaulthex = paramval.data(); - if (defaulthex) - _value = atoi(defaulthex); + if (defaulthex) { + _color.setValue(atoi(defaulthex)); + } + _color_changed = _color.signal_changed.connect(sigc::mem_fun(this, &ParamColor::_onColorChanged)); + } void ParamColor::string(std::string &string) const { char str[16]; - sprintf(str, "%i", _value); + snprintf(str, 16, "%i", _color.value()); string += str; } Gtk::Widget *ParamColor::get_widget( SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/, sigc::signal<void> * changeSignal ) { - if (_gui_hidden) return NULL; + using Inkscape::UI::Widget::ColorNotebook; + + if (_gui_hidden) return NULL; _changeSignal = new sigc::signal<void>(*changeSignal); - Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4)); - SPColorSelector* spColorSelector = (SPColorSelector*)sp_color_selector_new(SP_TYPE_COLOR_NOTEBOOK); - ColorSelector* colorSelector = spColorSelector->base; - if (_value < 1) { - _value = 0xFF000000; + if (_color.value() < 1) { + _color_changed.block(true); + _color.setValue(0xFF000000); + _color_changed.block(false); } - SPColor *color = new SPColor( _value ); - float alpha = (_value & 0xff) / 255.0F; - colorSelector->setColorAlpha(*color, alpha); - - hbox->pack_start (*Glib::wrap(&spColorSelector->vbox), true, true, 0); - g_signal_connect(G_OBJECT(spColorSelector), "changed", G_CALLBACK(sp_color_param_changed), (void*)this); - gtk_widget_show(GTK_WIDGET(spColorSelector)); + Gtk::HBox *hbox = Gtk::manage(new Gtk::HBox(false, 4)); + Gtk::Widget *selector = Gtk::manage(new ColorNotebook(_color)); + hbox->pack_start (*selector, true, true, 0); + selector->show(); hbox->show(); - - return dynamic_cast<Gtk::Widget *>(hbox); + return hbox; } -void sp_color_param_changed(SPColorSelector *csel, GObject *obj) +void ParamColor::_onColorChanged() { - const SPColor color = csel->base->getColor(); - float alpha = csel->base->getAlpha(); - - ParamColor* ptr = reinterpret_cast<ParamColor*>(obj); - ptr->set(color.toRGBA32( alpha ), NULL, NULL); - - ptr->_changeSignal->emit(); + if (_changeSignal) + _changeSignal->emit(); } }; /* namespace Extension */ diff --git a/src/extension/param/color.h b/src/extension/param/color.h index 9894965a9..ed2e57ceb 100644 --- a/src/extension/param/color.h +++ b/src/extension/param/color.h @@ -9,6 +9,7 @@ */ #include "parameter.h" +#include "ui/selected-color.h" class SPDocument; @@ -25,14 +26,17 @@ namespace Extension { class ParamColor : public Parameter { private: - guint32 _value; + void _onColorChanged(); + + Inkscape::UI::SelectedColor _color; + sigc::connection _color_changed; public: ParamColor(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml); virtual ~ParamColor(void); /** Returns \c _value, with a \i const to protect it. */ - guint32 get( SPDocument const * /*doc*/, Inkscape::XML::Node const * /*node*/ ) const { return _value; } + guint32 get( SPDocument const * /*doc*/, Inkscape::XML::Node const * /*node*/ ) const { return _color.value(); } guint32 set (guint32 in, SPDocument * doc, Inkscape::XML::Node * node); @@ -44,6 +48,7 @@ public: virtual void string (std::string &string) const; sigc::signal<void> * _changeSignal; + }; // class ParamColor } // namespace Extension diff --git a/src/extension/param/parameter.cpp b/src/extension/param/parameter.cpp index 202b8110f..8c99ee55d 100644 --- a/src/extension/param/parameter.cpp +++ b/src/extension/param/parameter.cpp @@ -15,6 +15,10 @@ # include "config.h" #endif +#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H +#include <glibmm/threads.h> +#endif + #ifdef linux // does the dollar sign need escaping when passed as string parameter? # define ESCAPE_DOLLAR_COMMANDLINE #endif @@ -26,8 +30,7 @@ #include "document-private.h" #include "sp-object.h" #include <color.h> -#include "widgets/sp-color-selector.h" -#include "widgets/sp-color-notebook.h" +#include "ui/widget/color-notebook.h" #include "parameter.h" #include "bool.h" diff --git a/src/knot-holder-entity.cpp b/src/knot-holder-entity.cpp index b66156b09..173025920 100644 --- a/src/knot-holder-entity.cpp +++ b/src/knot-holder-entity.cpp @@ -140,19 +140,19 @@ KnotHolderEntity::snap_knot_position_constrained(Geom::Point const &p, Inkscape: static gdouble sp_pattern_extract_theta(SPPattern const *pat) { - Geom::Affine transf = pat->patternTransform; + Geom::Affine transf = pat->getTransform(); return Geom::atan2(transf.xAxis()); } static Geom::Point sp_pattern_extract_scale(SPPattern const *pat) { - Geom::Affine transf = pat->patternTransform; + Geom::Affine transf = pat->getTransform(); return Geom::Point( transf.expansionX(), transf.expansionY() ); } static Geom::Point sp_pattern_extract_trans(SPPattern const *pat) { - return Geom::Point(pat->patternTransform[4], pat->patternTransform[5]); + return Geom::Point(pat->getTransform()[4], pat->getTransform()[5]); } void @@ -191,7 +191,7 @@ PatternKnotHolderEntityAngle::knot_get() const { SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer()); - gdouble x = pattern_width(pat); + gdouble x = pat->width(); gdouble y = 0; Geom::Point delta = Geom::Point(x,y); Geom::Point scale = sp_pattern_extract_scale(pat); @@ -240,8 +240,8 @@ PatternKnotHolderEntityScale::knot_set(Geom::Point const &p, Geom::Point const & // Get the new scale from the position of the knotholder Geom::Point d = p_snapped - sp_pattern_extract_trans(pat); - gdouble pat_x = pattern_width(pat); - gdouble pat_y = pattern_height(pat); + gdouble pat_x = pat->width(); + gdouble pat_y = pat->height(); Geom::Scale scl(1); if ( state & GDK_CONTROL_MASK ) { // if ctrl is pressed: use 1:1 scaling @@ -267,10 +267,10 @@ PatternKnotHolderEntityScale::knot_get() const { SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer()); - gdouble x = pattern_width(pat); - gdouble y = pattern_height(pat); + gdouble x = pat->width(); + gdouble y = pat->height(); Geom::Point delta = Geom::Point(x,y); - Geom::Affine a = pat->patternTransform; + Geom::Affine a = pat->getTransform(); a[4] = 0; a[5] = 0; delta = delta * a; diff --git a/src/libnrtype/font-lister.cpp b/src/libnrtype/font-lister.cpp index a6ab3b239..70374864a 100644 --- a/src/libnrtype/font-lister.cpp +++ b/src/libnrtype/font-lister.cpp @@ -335,7 +335,7 @@ Glib::ustring FontLister::system_fontspec(Glib::ustring fontspec) PangoFontDescription *descr = pango_font_description_from_string(fontspec.c_str()); font_instance *res = (font_factory::Default())->Face(descr); - if (res->pFont) { + if (res && res->pFont) { PangoFontDescription *nFaceDesc = pango_font_describe(res->pFont); out = sp_font_description_get_family(nFaceDesc); } diff --git a/src/libuemf/uemf.h b/src/libuemf/uemf.h index 53426cb55..f6ed7da03 100644 --- a/src/libuemf/uemf.h +++ b/src/libuemf/uemf.h @@ -95,8 +95,8 @@ these WMF enumerations is by referencing the following table: /* File: uemf.h -Version: 0.0.31 -Date: 23-APR-2015 +Version: 0.0.32 +Date: 28-APR-2015 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu Copyright: 2015 David Mathog and California Institute of Technology (Caltech) @@ -168,7 +168,12 @@ extern "C" { #define U_ROUND(A) ( (A) > 0 ? floor((A)+0.5) : ( (A) < 0 ? -floor(-(A)+0.5) : (A) ) ) #define MAKE_MIN_PTR(A,B) ( A < B ? A : B) -#define IS_MEM_UNSAFE(A,B,C) ( (int8_t *)(A) > (int8_t *)(C) ? 1 : ((int8_t *)(C) - (int8_t *)(A) >= (int)(B) ? 0 : 1 )) //!< Return 1 when a region of memory starting at A of B bytes extends beyond pointer C +/* This is tricky. The next one can be called with a size which is either an int or an unsigned int. + The former can be negative, which is obviously wrong, but testing for that means that the size cannot + be more than INT_MAX/2. Accept that limitation since no reasonable EMF record or file should ever be that large. + B must be an INT or size_t. + If a uint16_t is used gcc complains about the first test. Force B to be at least as big as int (at run time) */ +#define IS_MEM_UNSAFE(A,B,C) ( (sizeof(B) < sizeof(int) || (int)(B)) < 0 ? 1 : ((int8_t *)(A) > (int8_t *)(C) ? 1 : ((int8_t *)(C) - (int8_t *)(A) >= (int)(B) ? 0 : 1 ))) //!< Return 1 when a region of memory starting at A of B bytes extends beyond pointer C /** @} */ diff --git a/src/libuemf/uemf_print.c b/src/libuemf/uemf_print.c index adcf54c0f..4bc9f0206 100644 --- a/src/libuemf/uemf_print.c +++ b/src/libuemf/uemf_print.c @@ -6,8 +6,8 @@ /* File: uemf_print.c -Version: 0.0.18 -Date: 25-MAR-2015 +Version: 0.0.20 +Date: 21-MAY-2015 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu Copyright: 2015 David Mathog and California Institute of Technology (Caltech) @@ -35,6 +35,31 @@ void U_swap4(void *ul, unsigned int count); //! \endcond /** + \brief calculate a CRC32 value for record + \returns CRC32 value calculated for record + \param record pointer to the first byte + \param Size number of bytes in the record + +Code based on example crc32b here: + http://www.hackersdelight.org/hdcodetxt/crc.c.txt +*/ +uint32_t lu_crc32(const char *record, uint32_t Size){ + const unsigned char *message = record; + uint32_t i, j; + uint32_t crc, mask; + + crc = 0xFFFFFFFF; + for(i=0;i<Size;i++){ // over all bytes + crc = crc ^ *message++; + for (j = 0; j < 8; j++) { // over all bits + mask = -(crc & 1); + crc = (crc >> 1) ^ (0xEDB88320 & mask); + } + } + return ~crc; +} + +/** \brief Print some number of hex bytes \param buf pointer to the first byte \param num number of bytes @@ -45,6 +70,7 @@ void hexbytes_print(uint8_t *buf,unsigned int num){ } } + /* ********************************************************************************************** These functions print standard objects used in the EMR records. The low level ones do not append EOL. @@ -2505,7 +2531,7 @@ int U_emf_onerec_print(const char *contents, const char *blimit, int recnum, siz uint32_t nSize; uint32_t iType; const char *record = contents + off; - + if(record < contents)return(-1); // offset wrapped /* Check that COMMON data in record can be touched without an access violation. If it cannot be @@ -2514,7 +2540,21 @@ int U_emf_onerec_print(const char *contents, const char *blimit, int recnum, siz */ if(!U_emf_record_sizeok(record, blimit, &nSize, &iType, 1))return(-1); - printf("%-30srecord:%5d type:%-4d offset:%8d rsize:%8d\n",U_emr_names(iType),recnum,iType,(int) off,nSize); + uint32_t crc; +#if U_BYTE_SWAP + //This is a Big Endian machine, EMF crc values must be calculated on Little Endian form + char *swapbuf=malloc(nSize); + if(!swapbuf)return(-1); + memcpy(swapbuf,record,nSize); + U_emf_endian(swapbuf,nSize,1); // BE to LE + crc=lu_crc32(swapbuf,nSize); + free(swapbuf); +#else + crc=lu_crc32(record,nSize); +#endif + printf("%-30srecord:%5d type:%-4d offset:%8d rsize:%8d crc32:%8.8X\n", + U_emr_names(iType),recnum,iType,(int) off,nSize,crc); + fflush(stdout); /* print the record header before checking further. diff --git a/src/libuemf/uemf_print.h b/src/libuemf/uemf_print.h index 6568b4cfa..088a8a302 100644 --- a/src/libuemf/uemf_print.h +++ b/src/libuemf/uemf_print.h @@ -6,8 +6,8 @@ /* File: uemf_print.h -Version: 0.0.7 -Date: 24-MAR-2015 +Version: 0.0.9 +Date: 21-MAY-2015 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu Copyright: 2015 David Mathog and California Institute of Technology (Caltech) @@ -21,6 +21,9 @@ extern "C" { #endif //! \cond +/* prototypes for miscellaneous */ +uint32_t lu_crc32(const char *record, uint32_t Size); + /* prototypes for objects used in EMR records */ void hexbytes_print(uint8_t *buf,unsigned int num); void colorref_print(U_COLORREF color); diff --git a/src/libuemf/upmf.c b/src/libuemf/upmf.c index 7d6349185..2ba818fa4 100644 --- a/src/libuemf/upmf.c +++ b/src/libuemf/upmf.c @@ -21,8 +21,8 @@ /* File: upmf.c -Version: 0.0.9 -Date: 25-MAR-2015 +Version: 0.0.10 +Date: 27-APR-2015 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu Copyright: 2015 David Mathog and California Institute of Technology (Caltech) @@ -6575,15 +6575,17 @@ int U_PMF_VARPOINTS_get(const char *contents, uint16_t Flags, int Elements, U_PM } } else if(Flags & U_PPF_C){ - for(XFS = YFS = 0.0; Elements; Elements--, pts++){ + for(XF = YF = 0.0; Elements; Elements--, pts++){ if(!U_PMF_POINT_get(&contents, &XF, &XF, blimit))break; /* this should never happen */ pts->X = XF; pts->Y = YF; } } else { - for(XFS = YFS = 0.0; Elements; Elements--, pts++){ - (void) U_PMF_POINTF_get(&contents, &(pts->X), &(pts->Y), blimit); + for(XF = YF = 0.0; Elements; Elements--, pts++){ + (void) U_PMF_POINTF_get(&contents, &XF, &YF, blimit); + pts->X = XF; + pts->Y = YF; } } if(Elements){ /* some error in the preceding */ diff --git a/src/libuemf/upmf_print.c b/src/libuemf/upmf_print.c index 7d9598b0d..58ff4edd0 100644 --- a/src/libuemf/upmf_print.c +++ b/src/libuemf/upmf_print.c @@ -6,8 +6,8 @@ /* File: upmf_print.c -Version: 0.0.5 -Date: 24-MAR-2015 +Version: 0.0.7 +Date: 21-MAY-2015 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu Copyright: 2015 David Mathog and California Institute of Technology (Caltech) @@ -142,7 +142,7 @@ int U_pmf_onerec_print(const char *contents, const char *blimit, int recnum, int int type = Header.Type & U_PMR_TYPE_MASK; /* strip the U_PMR_RECFLAG bit, leaving the indexable part */ if(type < U_PMR_MIN || type > U_PMR_MAX)return(-1); /* unknown EMF+ record type */ - status = U_PMF_CMN_HDR_print(Header, recnum, off); /* EMF+ part */ + status = U_PMF_CMN_HDR_print(contents, Header, recnum, off); /* EMF+ part */ /* Buggy EMF+ can set the continue bit and then do something else. In that case, force out the pending Object. Side effect - clears the pending object. */ @@ -222,14 +222,16 @@ int U_pmf_onerec_print(const char *contents, const char *blimit, int recnum, int /** \brief Print data from a U_PMF_CMN_HDR object \return number of bytes in record, 0 on error + \param contents pointer to a buffer holding this EMF+ record \param Header Header of the record \param precnum EMF+ record number in file. \param off Offset in file to the start of this EMF+ record. common structure present at the beginning of all(*) EMF+ records */ -int U_PMF_CMN_HDR_print(U_PMF_CMN_HDR Header, int precnum, int off){ - printf(" %-29srec+:%5d type:%X offset:%8d rsize:%8u dsize:%8u flags:%4.4X\n", - U_pmr_names(Header.Type &U_PMR_TYPE_MASK),precnum, Header.Type,off,Header.Size,Header.DataSize,Header.Flags); +int U_PMF_CMN_HDR_print(const char *contents, U_PMF_CMN_HDR Header, int precnum, int off){ + printf(" %-29srec+:%5d type:%X offset:%8d rsize:%8u dsize:%8u flags:%4.4X crc32:%8.8X\n", + U_pmr_names(Header.Type &U_PMR_TYPE_MASK),precnum, Header.Type,off,Header.Size,Header.DataSize,Header.Flags, + lu_crc32(contents,Header.Size)); return((int) Header.Size); } @@ -1852,7 +1854,12 @@ int U_PMF_TRANSFORMMATRIX_print(const char *contents, const char *blimit){ EMF+ manual 2.2.2.47, Microsoft name: EmfPlusTransformMatrix Object */ int U_PMF_TRANSFORMMATRIX2_print(U_PMF_TRANSFORMMATRIX *Tm){ - printf(" Matrix:{%f,%f,%f,%f,%f,%f}", Tm->m11, Tm->m12, Tm->m21, Tm->m22, Tm->dX, Tm->dY); + if(Tm){ + printf(" Matrix:{%f,%f,%f,%f,%f,%f}", Tm->m11, Tm->m12, Tm->m21, Tm->m22, Tm->dX, Tm->dY); + } + else { + printf(" Matrix:(None)"); + } return(1); } diff --git a/src/libuemf/upmf_print.h b/src/libuemf/upmf_print.h index fe1c57d60..a25374487 100644 --- a/src/libuemf/upmf_print.h +++ b/src/libuemf/upmf_print.h @@ -6,8 +6,8 @@ /* File: upmf_print.h -Version: 0.0.4 -Date: 24-MAR-2015 +Version: 0.0.5 +Date: 28-APR-2015 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu Copyright: 2015 David Mathog and California Institute of Technology (Caltech) @@ -23,7 +23,7 @@ extern "C" { #include "upmf.h" /* includes uemf.h */ /* prototypes for simple types and enums used in PMR records */ -int U_PMF_CMN_HDR_print(U_PMF_CMN_HDR Header, int precnum, int off); +int U_PMF_CMN_HDR_print(const char *contents, U_PMF_CMN_HDR Header, int precnum, int off); int U_PMF_UINT8_ARRAY_print(const char *Start, const uint8_t *Array, int Elements, char *End); int U_PMF_BRUSHTYPEENUMERATION_print(int otype); int U_PMF_HATCHSTYLEENUMERATION_print(int hstype); diff --git a/src/libuemf/uwmf.c b/src/libuemf/uwmf.c index 35d38f69a..62e3d3c06 100644 --- a/src/libuemf/uwmf.c +++ b/src/libuemf/uwmf.c @@ -19,8 +19,8 @@ /* File: uwmf.c -Version: 0.0.16 -Date: 25-MAR-2015 +Version: 0.0.17 +Date: 28-MAR-2015 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu Copyright: 2014 David Mathog and California Institute of Technology (Caltech) @@ -696,7 +696,8 @@ int packed_DIB_safe( int usedbytes; if(!bitmapinfo_safe(record, blimit))return(0); // this DIB has issues with colors fitting into the record - uint32_t width, height, colortype, numCt, invert; // these values will be set in get_DIB_params + uint32_t numCt; // these values will be set in get_DIB_params + int32_t width, height, colortype, invert; // these values will be set in get_DIB_params // next call returns pointers and values, but allocates no memory dibparams = wget_DIB_params(record, &px, (const U_RGBQUAD **) &ct, &numCt, &width, &height, &colortype, &invert); // sanity checking @@ -1564,7 +1565,7 @@ int wmf_finish( #if U_BYTE_SWAP //This is a Big Endian machine, WMF data must be Little Endian - U_wmf_endian(wt->buf,wt->used,1); + U_wmf_endian(wt->buf,wt->used,1,0); // BE to LE, entire file #endif (void) U_wmr_properties(U_WMR_INVALID); /* force the release of the lookup table memory, returned value is irrelevant */ @@ -1610,7 +1611,7 @@ int wmf_readdata( else { #if U_BYTE_SWAP //This is a Big Endian machine, WMF data is Little Endian - U_wmf_endian(*contents,*length,0); // LE to BE + U_wmf_endian(*contents,*length,0,0); // LE to BE, entire file #endif } } @@ -4720,10 +4721,10 @@ int U_WMRCORE_PALETTE_get( */ void U_BITMAPCOREHEADER_get( const char *BmiCh, - int32_t *Size, - int32_t *Width, - int32_t *Height, - int32_t *BitCount + uint32_t *Size, + int32_t *Width, + int32_t *Height, + int32_t *BitCount ){ uint32_t utmp4; uint16_t utmp2; @@ -4800,14 +4801,14 @@ int wget_DIB_params( const char *dib, const char **px, const U_RGBQUAD **ct, - int32_t *numCt, - int32_t *width, - int32_t *height, - int32_t *colortype, - int32_t *invert + uint32_t *numCt, + int32_t *width, + int32_t *height, + int32_t *colortype, + int32_t *invert ){ uint32_t bic; - int32_t Size; + uint32_t Size; bic = U_BI_RGB; // this information is not in the coreheader; U_BITMAPCOREHEADER_get(dib, &Size, width, height, colortype); if(Size != 0xC ){ //BitmapCoreHeader @@ -4816,7 +4817,7 @@ int wget_DIB_params( */ uint32_t uig4; int32_t ig4; - U_BITMAPINFOHEADER_get(dib, &uig4, width, height,&uig4, (uint32_t *) colortype, &bic, &uig4, &ig4, &ig4,&uig4, &uig4); + U_BITMAPINFOHEADER_get(dib, &uig4, width, height,&uig4, (uint32_t *) colortype, &bic, &uig4, &ig4, &ig4, &uig4, &uig4); } if(*height < 0){ *height = -*height; @@ -5559,7 +5560,8 @@ int U_WMRPOLYGON_get( ){ int size = U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRPOLYGON), NULL, Length, Data); if(size){ - if(IS_MEM_UNSAFE(*Data, (*Length)*sizeof(U_POINT16), contents+size))return(0); + int iLength = (*Length)*sizeof(U_POINT16); + if(IS_MEM_UNSAFE(*Data, iLength, contents+size))return(0); } return size; } @@ -5578,7 +5580,8 @@ int U_WMRPOLYLINE_get( ){ int size = U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRPOLYGON), NULL, Length, Data); if(size){ - if(IS_MEM_UNSAFE(*Data, (*Length)*sizeof(U_POINT16), contents+size))return(0); + int iLength = (*Length)*sizeof(U_POINT16); + if(IS_MEM_UNSAFE(*Data, iLength, contents+size))return(0); } return size; } @@ -5605,7 +5608,8 @@ int U_WMRESCAPE_get( ){ int size = U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRESCAPE), Escape, Length, Data); if(size){ - if(IS_MEM_UNSAFE(*Data, *Length, contents+size))return(0); + int iLength=*Length; + if(IS_MEM_UNSAFE(*Data, iLength, contents+size))return(0); } return size; } diff --git a/src/libuemf/uwmf.h b/src/libuemf/uwmf.h index 2237d2221..027de8e06 100644 --- a/src/libuemf/uwmf.h +++ b/src/libuemf/uwmf.h @@ -36,11 +36,11 @@ /* File: uwmf.h -Version: 0.0.11 -Date: 23-APR-2014 +Version: 0.0.12 +Date: 28-APR-2015 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu -Copyright: 2014 David Mathog and California Institute of Technology (Caltech) +Copyright: 2015 David Mathog and California Institute of Technology (Caltech) */ #ifndef _UWMF_ @@ -2407,8 +2407,8 @@ int wmr_arc_points(U_RECT16 rclBox, U_POINT16 ArcStart, U_POINT16 ArcEn void U_BITMAPINFOHEADER_get(const char *Bmih, uint32_t *Size, int32_t *Width, int32_t *Height, uint32_t *Planes, uint32_t *BitCount, uint32_t *Compression, uint32_t *SizeImage, int32_t *XPelsPerMeter, int32_t *YPelsPerMeter, uint32_t *ClrUsed, uint32_t *ClrImportant); -void U_BITMAPCOREHEADER_get(const char *BmiCh, int32_t *Size, int32_t *Width, int32_t *Height, int32_t *BitCount); -int wget_DIB_params(const char *dib, const char **px, const U_RGBQUAD **ct, int32_t *numCt, +void U_BITMAPCOREHEADER_get(const char *BmiCh, uint32_t *Size, int32_t *Width, int32_t *Height, int32_t *BitCount); +int wget_DIB_params(const char *dib, const char **px, const U_RGBQUAD **ct, uint32_t *numCt, int32_t *width, int32_t *height, int32_t *colortype, int32_t *invert); int U_WMREOF_get(const char *contents); int U_WMRSETBKCOLOR_get(const char *contents, U_COLORREF *Color); diff --git a/src/libuemf/uwmf_endian.c b/src/libuemf/uwmf_endian.c index 38a321ad0..de0b3ef87 100644 --- a/src/libuemf/uwmf_endian.c +++ b/src/libuemf/uwmf_endian.c @@ -6,11 +6,11 @@ /* File: uwmf_endian.c -Version: 0.1.3 -Date: 27-MAR-2014 +Version: 0.1.4 +Date: 28-APR-2015 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu -Copyright: 2014 David Mathog and California Institute of Technology (Caltech) +Copyright: 2015 David Mathog and California Institute of Technology (Caltech) */ #ifdef __cplusplus @@ -1470,21 +1470,24 @@ void U_WMRCREATEREGION_swap(char *record, int torev){ \param contents pointer to the buffer holding the entire EMF in memory \param length number of bytes in the buffer \param torev 1 for native to reversed, 0 for reversed to native + \param onerec 1 if this is operating on a single record instead of an entire file Normally this would be called immediately before writing the data to a file or immediately after reading the data from a file. */ -int U_wmf_endian(char *contents, size_t length, int torev){ - size_t off; +int U_wmf_endian(char *contents, size_t length, int torev, int onerec){ + size_t off=0; uint32_t OK, Size16; uint8_t iType; char *record; int recnum, offset; record = contents; - off = wmfheader_swap(record,torev); fflush(stdout); /* WMF header is not a normal record, handle it separately */ - record += off; - offset = off; + if(!onerec){ + off = wmfheader_swap(record,torev); fflush(stdout); /* WMF header is not a normal record, handle it separately */ + record += off; + offset = off; + } OK = 1; recnum = 1; /* used when debugging */ @@ -1759,6 +1762,7 @@ int U_wmf_endian(char *contents, size_t length, int torev){ record += 2*Size16; offset += 2*Size16; recnum++; + if(onerec)break; } //end of while return(1); } diff --git a/src/libuemf/uwmf_endian.h b/src/libuemf/uwmf_endian.h index 57fd4ae44..6ce7f1984 100644 --- a/src/libuemf/uwmf_endian.h +++ b/src/libuemf/uwmf_endian.h @@ -6,11 +6,11 @@ /* File: uwmf_endian.h -Version: 0.0.2 -Date: 26-NOV-2013 +Version: 0.0.3 +Date: 28-APR-2015 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu -Copyright: 2013 David Mathog and California Institute of Technology (Caltech) +Copyright: 2015 David Mathog and California Institute of Technology (Caltech) */ #ifndef _UWMF_ENDIAN_ @@ -24,7 +24,7 @@ extern "C" { //! \cond // prototypes -int U_wmf_endian(char *contents, size_t length, int torev); +int U_wmf_endian(char *contents, size_t length, int torev, int onerec); //! \endcond #ifdef __cplusplus diff --git a/src/libuemf/uwmf_print.c b/src/libuemf/uwmf_print.c index dd460b2b0..d6d1b584e 100644 --- a/src/libuemf/uwmf_print.c +++ b/src/libuemf/uwmf_print.c @@ -6,11 +6,11 @@ /* File: uwmf_print.c -Version: 0.0.4 -Date: 05-FEB-2014 +Version: 0.0.6 +Date: 21-MAY-2015 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu -Copyright: 2014 David Mathog and California Institute of Technology (Caltech) +Copyright: 2015 David Mathog and California Institute of Technology (Caltech) */ #ifdef __cplusplus @@ -1351,13 +1351,20 @@ int U_wmf_onerec_print(const char *contents, const char *blimit, int recnum, siz iType = *(uint8_t *)(contents + offsetof(U_METARECORD, iType ) ); -#if 1 - printf("%-30srecord:%5d type:%-4u offset:%8d rsize:%8u\n", - U_wmr_names(iType), recnum, iType, (int) off, (int) size); -#else /* show record checksums, this is NOT portable, result changes with endian type, useful for debugging */ - printf("%-30srecord:%5d type:%-4u offset:%8d size:%8u recchecksum:%u\n", - U_wmr_names(iType), recnum, iType, (int) off, (int) size, U_16_checksum((int16_t *)contents, size)); + uint32_t crc; +#if U_BYTE_SWAP + //This is a Big Endian machine, WMF crc values must be calculated on Little Endian form + char *swapbuf=malloc(size); + if(!swapbuf)return(-1); + memcpy(swapbuf,contents,size); + U_wmf_endian(swapbuf,size,1,1); // BE to LE + crc=lu_crc32(swapbuf,size); + free(swapbuf); +#else + crc=lu_crc32(contents,size); #endif + printf("%-30srecord:%5d type:%-4u offset:%8d rsize:%8u crc32:%8.8X\n", + U_wmr_names(iType), recnum, iType, (int) off, (int) size, crc); switch (iType) { diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index d3ca781e9..332d81777 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -358,7 +358,6 @@ Effect::Effect(LivePathEffectObject *lpeobject) lpeobj(lpeobject), concatenate_before_pwd2(false), sp_lpe_item(NULL), - defaultUnit("px"), current_zoom(1), sp_curve(NULL), provides_own_flash_paths(true), // is automatically set to false if providesOwnFlashPaths() is not overridden @@ -448,7 +447,6 @@ void Effect::doOnRemove (SPLPEItem const* /*lpeitem*/) void Effect::doOnApply_impl(SPLPEItem const* lpeitem) { sp_lpe_item = const_cast<SPLPEItem *>(lpeitem); - defaultUnit = sp_lpe_item->document->getDisplayUnit()->abbr; /*sp_curve = SP_SHAPE(sp_lpe_item)->getCurve(); pathvector_before_effect = sp_curve->get_pathvector();*/ doOnApply(lpeitem); @@ -457,7 +455,6 @@ void Effect::doOnApply_impl(SPLPEItem const* lpeitem) void Effect::doBeforeEffect_impl(SPLPEItem const* lpeitem) { sp_lpe_item = const_cast<SPLPEItem *>(lpeitem); - defaultUnit = sp_lpe_item->document->getDisplayUnit()->abbr; //printf("(SPLPEITEM*) %p\n", sp_lpe_item); SPShape * shape = dynamic_cast<SPShape *>(sp_lpe_item); if(shape){ diff --git a/src/live_effects/effect.h b/src/live_effects/effect.h index 63d357481..ea57ff243 100644 --- a/src/live_effects/effect.h +++ b/src/live_effects/effect.h @@ -159,7 +159,6 @@ protected: bool concatenate_before_pwd2; SPLPEItem * sp_lpe_item; // these get stored in doBeforeEffect_impl, and derived classes may do as they please with them. - Glib::ustring defaultUnit; // these get stored in doBeforeEffect_impl, and derived classes may do as they please with them. double current_zoom; std::vector<Geom::Point> selectedNodesPoints; SPCurve * sp_curve; diff --git a/src/live_effects/lpe-fillet-chamfer.cpp b/src/live_effects/lpe-fillet-chamfer.cpp index fe03781d4..992c45a43 100644 --- a/src/live_effects/lpe-fillet-chamfer.cpp +++ b/src/live_effects/lpe-fillet-chamfer.cpp @@ -29,7 +29,6 @@ // for programmatically updating knots #include "ui/tools-switch.h" -#include <util/units.h> // TODO due to internal breakage in glibmm headers, this must be last: #include <glibmm/i18n.h> @@ -57,7 +56,6 @@ LPEFilletChamfer::LPEFilletChamfer(LivePathEffectObject *lpeobject) : only_selected(_("Change only selected nodes"), _("Change only selected nodes"), "only_selected", &wr, this, false), flexible(_("Flexible radius size (%)"), _("Flexible radius size (%)"), "flexible", &wr, this, false), use_knot_distance(_("Use knots distance instead radius"), _("Use knots distance instead radius"), "use_knot_distance", &wr, this, false), - unit(_("Unit:"), _("Unit"), "unit", &wr, this), method(_("Method:"), _("Fillets methods"), "method", FMConverter, &wr, this, FM_AUTO), radius(_("Radius (unit or %):"), _("Radius, in unit or %"), "radius", &wr, this, 0.), chamfer_steps(_("Chamfer steps:"), _("Chamfer steps"), "chamfer_steps", &wr, this, 0), @@ -65,7 +63,6 @@ LPEFilletChamfer::LPEFilletChamfer(LivePathEffectObject *lpeobject) : helper_size(_("Helper size with direction:"), _("Helper size with direction"), "helper_size", &wr, this, 0) { registerParameter(&fillet_chamfer_values); - registerParameter(&unit); registerParameter(&method); registerParameter(&radius); registerParameter(&chamfer_steps); @@ -223,7 +220,7 @@ void LPEFilletChamfer::updateFillet() { double power = 0; if (!flexible) { - power = Inkscape::Util::Quantity::convert(radius, unit.get_abbreviation(), defaultUnit) * -1; + power = radius * -1; } else { power = radius; } @@ -444,9 +441,7 @@ void LPEFilletChamfer::doBeforeEffect(SPLPEItem const *lpeItem) } else { fillet_chamfer_values.set_helper_size(helper_size); } - fillet_chamfer_values.set_document_unit(defaultUnit); fillet_chamfer_values.set_use_distance(use_knot_distance); - fillet_chamfer_values.set_unit(unit.get_abbreviation()); SPCurve *c = SP_IS_PATH(lpeItem) ? static_cast<SPPath const *>(lpeItem) ->get_original_curve() : SP_SHAPE(lpeItem)->getCurve(); diff --git a/src/live_effects/lpe-fillet-chamfer.h b/src/live_effects/lpe-fillet-chamfer.h index 9c91a18b5..290a37f92 100644 --- a/src/live_effects/lpe-fillet-chamfer.h +++ b/src/live_effects/lpe-fillet-chamfer.h @@ -66,7 +66,6 @@ private: BoolParam only_selected; BoolParam flexible; BoolParam use_knot_distance; - UnitParam unit; EnumParam<FilletMethod> method; ScalarParam radius; ScalarParam chamfer_steps; diff --git a/src/live_effects/lpe-roughen.cpp b/src/live_effects/lpe-roughen.cpp index 44ff54554..33ffd96d6 100644 --- a/src/live_effects/lpe-roughen.cpp +++ b/src/live_effects/lpe-roughen.cpp @@ -20,7 +20,6 @@ #include "live_effects/parameter/parameter.h" #include "helper/geom.h" #include <glibmm/i18n.h> -#include <util/units.h> #include <cmath> namespace Inkscape { @@ -36,7 +35,6 @@ DMConverter(DivisionMethodData, DM_END); LPERoughen::LPERoughen(LivePathEffectObject *lpeobject) : Effect(lpeobject), // initialise your parameters here: - unit(_("Unit"), _("Unit"), "unit", &wr, this), method(_("Method"), _("Division method"), "method", DMConverter, &wr, this, DM_SEGMENTS), max_segment_size(_("Max. segment size"), _("Max. segment size"), @@ -54,7 +52,6 @@ LPERoughen::LPERoughen(LivePathEffectObject *lpeobject) shift_node_handles(_("Shift node handles"), _("Shift node handles"), "shift_node_handles", &wr, this, true) { - registerParameter(&unit); registerParameter(&method); registerParameter(&max_segment_size); registerParameter(&segments); @@ -98,14 +95,6 @@ Gtk::Widget *LPERoughen::newWidget() if ((*it)->widget_is_visible) { Parameter *param = *it; Gtk::Widget *widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget()); - if (param->param_key == "unit") { - Gtk::Label *unit_label = Gtk::manage(new Gtk::Label( - Glib::ustring(_("<b>Roughen unit</b>")), Gtk::ALIGN_START)); - unit_label->set_use_markup(true); - vbox->pack_start(*unit_label, false, false, 2); - vbox->pack_start(*Gtk::manage(new Gtk::HSeparator()), - Gtk::PACK_EXPAND_WIDGET); - } if (param->param_key == "method") { Gtk::Label *method_label = Gtk::manage(new Gtk::Label( Glib::ustring(_("<b>Add nodes</b> Subdivide each segment")), @@ -160,11 +149,8 @@ double LPERoughen::sign(double random_number) Geom::Point LPERoughen::randomize() { - Inkscape::Util::Unit const *svg_units = SP_ACTIVE_DESKTOP->namedview->svg_units; - double displace_x_parsed = Inkscape::Util::Quantity::convert( - displace_x * global_randomize, unit.get_abbreviation(), svg_units->abbr); - double displace_y_parsed = Inkscape::Util::Quantity::convert( - displace_y * global_randomize, unit.get_abbreviation(), svg_units->abbr); + double displace_x_parsed = displace_x * global_randomize; + double displace_y_parsed = displace_y * global_randomize; Geom::Point output = Geom::Point(sign(displace_x_parsed), sign(displace_y_parsed)); return output; @@ -175,7 +161,6 @@ void LPERoughen::doEffect(SPCurve *curve) Geom::PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(curve->get_pathvector()); curve->reset(); - Inkscape::Util::Unit const *svg_units = SP_ACTIVE_DESKTOP->namedview->svg_units; for (Geom::PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) { if (path_it->empty()) @@ -220,8 +205,7 @@ void LPERoughen::doEffect(SPCurve *curve) } else { nCurve->lineto(point3); } - double length = Inkscape::Util::Quantity::convert( - curve_it1->length(0.001), svg_units->abbr, unit.get_abbreviation()); + double length = curve_it1->length(0.001); std::size_t splits = 0; if (method == DM_SEGMENTS) { splits = segments; diff --git a/src/live_effects/lpe-roughen.h b/src/live_effects/lpe-roughen.h index ed9f06cf7..2b285cd40 100644 --- a/src/live_effects/lpe-roughen.h +++ b/src/live_effects/lpe-roughen.h @@ -17,7 +17,6 @@ #include "live_effects/parameter/parameter.h" #include "live_effects/parameter/path.h" #include "live_effects/parameter/bool.h" -#include "live_effects/parameter/unit.h" #include "live_effects/parameter/random.h" namespace Inkscape { @@ -45,7 +44,6 @@ public: virtual Gtk::Widget *newWidget(); private: - UnitParam unit; EnumParam<DivisionMethod> method; ScalarParam max_segment_size; ScalarParam segments; diff --git a/src/live_effects/parameter/filletchamferpointarray.cpp b/src/live_effects/parameter/filletchamferpointarray.cpp index cf11d52fc..a3ff4c96f 100644 --- a/src/live_effects/parameter/filletchamferpointarray.cpp +++ b/src/live_effects/parameter/filletchamferpointarray.cpp @@ -354,11 +354,6 @@ void FilletChamferPointArrayParam::set_pwd2( last_pwd2_normal = pwd2_normal_in; } -void FilletChamferPointArrayParam::set_document_unit(Glib::ustring value_document_unit) -{ - documentUnit = value_document_unit; -} - void FilletChamferPointArrayParam::set_helper_size(int hs) { helper_size = hs; @@ -374,11 +369,6 @@ void FilletChamferPointArrayParam::set_use_distance(bool use_knot_distance ) use_distance = use_knot_distance; } -void FilletChamferPointArrayParam::set_unit(const gchar *abbr) -{ - unit = abbr; -} - void FilletChamferPointArrayParam::updateCanvasIndicators() { std::vector<Point> ts = data(); @@ -812,7 +802,7 @@ void FilletChamferPointArrayParamKnotHolderEntity::knot_click(guint state) bool aprox = (A[0].degreesOfFreedom() != 2 || B[0].degreesOfFreedom() != 2) && !_pparam->use_distance?true:false; Geom::Point offset = Geom::Point(xModified, _pparam->_vector.at(_index).y()); Inkscape::UI::Dialogs::FilletChamferPropertiesDialog::showDialog( - this->desktop, offset, this, _pparam->unit, _pparam->use_distance, aprox, _pparam->documentUnit); + this->desktop, offset, this, _pparam->use_distance, aprox); } } diff --git a/src/live_effects/parameter/filletchamferpointarray.h b/src/live_effects/parameter/filletchamferpointarray.h index bc05ecfc4..48cd26d2d 100644 --- a/src/live_effects/parameter/filletchamferpointarray.h +++ b/src/live_effects/parameter/filletchamferpointarray.h @@ -53,8 +53,6 @@ public: virtual void set_helper_size(int hs); virtual void set_use_distance(bool use_knot_distance); virtual void set_chamfer_steps(int value_chamfer_steps); - virtual void set_document_unit(Glib::ustring value_document_unit); - virtual void set_unit(const gchar *abbr); virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector<Geom::PathVector> &hp_vec); virtual bool providesKnotHolderEntities() const { @@ -89,8 +87,6 @@ private: int helper_size; int chamfer_steps; bool use_distance; - const gchar *unit; - Glib::ustring documentUnit; Geom::PathVector hp; Geom::Piecewise<Geom::D2<Geom::SBasis> > last_pwd2; diff --git a/src/rdf.cpp b/src/rdf.cpp index 16344e520..938dc60c6 100644 --- a/src/rdf.cpp +++ b/src/rdf.cpp @@ -39,7 +39,7 @@ </Agent></dc:rights> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> <dc:source rdf:resource="source"/> - <license rdf:resource="http://creativecommons.org/licenses/by/2.0/" + <license rdf:resource="http://creativecommons.org/licenses/by/4.0/" /> </Work> @@ -173,32 +173,32 @@ struct rdf_double_t rdf_license_ofl [] = { struct rdf_license_t rdf_licenses [] = { { N_("CC Attribution"), - "http://creativecommons.org/licenses/by/3.0/", + "http://creativecommons.org/licenses/by/4.0/", rdf_license_cc_a, }, { N_("CC Attribution-ShareAlike"), - "http://creativecommons.org/licenses/by-sa/3.0/", + "http://creativecommons.org/licenses/by-sa/4.0/", rdf_license_cc_a_sa, }, { N_("CC Attribution-NoDerivs"), - "http://creativecommons.org/licenses/by-nd/3.0/", + "http://creativecommons.org/licenses/by-nd/4.0/", rdf_license_cc_a_nd, }, { N_("CC Attribution-NonCommercial"), - "http://creativecommons.org/licenses/by-nc/3.0/", + "http://creativecommons.org/licenses/by-nc/4.0/", rdf_license_cc_a_nc, }, { N_("CC Attribution-NonCommercial-ShareAlike"), - "http://creativecommons.org/licenses/by-nc-sa/3.0/", + "http://creativecommons.org/licenses/by-nc-sa/4.0/", rdf_license_cc_a_nc_sa, }, { N_("CC Attribution-NonCommercial-NoDerivs"), - "http://creativecommons.org/licenses/by-nc-nd/3.0/", + "http://creativecommons.org/licenses/by-nc-nd/4.0/", rdf_license_cc_a_nc_nd, }, diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 2cd4f6b4e..16585413e 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -107,6 +107,7 @@ SPCycleType SP_CYCLING = SP_CYCLE_FOCUS; #include "live_effects/effect.h" #include "live_effects/effect-enum.h" #include "live_effects/parameter/originalpath.h" +#include "layer-manager.h" #include "enums.h" #include "sp-item-group.h" @@ -438,7 +439,7 @@ static void add_ids_recursive(std::vector<const gchar *> &ids, SPObject *obj) } } -void sp_selection_duplicate(SPDesktop *desktop, bool suppressDone) +void sp_selection_duplicate(SPDesktop *desktop, bool suppressDone, bool duplicateLayer) { if (desktop == NULL) { return; @@ -449,12 +450,17 @@ void sp_selection_duplicate(SPDesktop *desktop, bool suppressDone) Inkscape::Selection *selection = desktop->getSelection(); // check if something is selected - if (selection->isEmpty()) { + if (selection->isEmpty() && !duplicateLayer) { desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to duplicate.")); return; } std::vector<Inkscape::XML::Node*> reprs(selection->reprList()); + if(duplicateLayer){ + reprs.clear(); + reprs.push_back(desktop->currentLayer()->getRepr()); + } + selection->clear(); // sorting items from different parents sorts each parent's subset without possibly mixing @@ -474,7 +480,10 @@ void sp_selection_duplicate(SPDesktop *desktop, bool suppressDone) Inkscape::XML::Node *parent = old_repr->parent(); Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc); - parent->appendChild(copy); + if(! duplicateLayer) + parent->appendChild(copy); + else + parent->addChild(copy, old_repr); if (relink_clones) { SPObject *old_obj = doc->getObjectByRepr(old_repr); @@ -535,8 +544,14 @@ void sp_selection_duplicate(SPDesktop *desktop, bool suppressDone) DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_DUPLICATE, _("Duplicate")); } - - selection->setReprList(newsel); + if(!duplicateLayer) + selection->setReprList(newsel); + else{ + SPObject* new_layer = doc->getObjectByRepr(newsel[0]); + gchar* name = g_strdup_printf(_("%s copy"), new_layer->label()); + desktop->layer_manager->renameLayer( new_layer, name, TRUE ); + g_free(name); + } } void sp_edit_clear_all(Inkscape::Selection *selection) @@ -1948,8 +1963,8 @@ std::vector<SPItem*> sp_get_same_fill_or_stroke_color(SPItem *sel, std::vector<S } } else if (dynamic_cast<SPPattern *>(sel_server) && dynamic_cast<SPPattern *>(iter_server)) { - SPPattern *sel_pat = pattern_getroot(dynamic_cast<SPPattern *>(sel_server)); - SPPattern *iter_pat = pattern_getroot(dynamic_cast<SPPattern *>(iter_server)); + SPPattern *sel_pat = dynamic_cast<SPPattern *>(sel_server)->rootPattern(); + SPPattern *iter_pat = dynamic_cast<SPPattern *>(iter_server)->rootPattern(); if (sel_pat == iter_pat) { match = true; } @@ -3297,7 +3312,7 @@ sp_selection_tile(SPDesktop *desktop, bool apply) int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); - gchar const *pat_id = pattern_tile(repr_copies, bbox, doc, + gchar const *pat_id = SPPattern::produce(repr_copies, bbox, doc, ( Geom::Affine(Geom::Translate(desktop->dt2doc(Geom::Point(r->min()[Geom::X], r->max()[Geom::Y])))) * parent_transform.inverse() ), @@ -3375,9 +3390,9 @@ void sp_selection_untile(SPDesktop *desktop) did = true; - SPPattern *pattern = pattern_getroot(basePat); + SPPattern *pattern = basePat->rootPattern(); - Geom::Affine pat_transform = pattern_patternTransform(basePat); + Geom::Affine pat_transform = basePat->getTransform(); pat_transform *= item->transform; for (SPObject *child = pattern->firstChild() ; child != NULL; child = child->next ) { @@ -3787,13 +3802,11 @@ void sp_selection_set_clipgroup(SPDesktop *desktop) clone->setAttribute("inkscape:transform-center-y", inner->attribute("inkscape:transform-center-y"), false); const Geom::Affine maskTransform(Geom::Affine::identity()); - GSList *templist = NULL; - - templist = g_slist_append(templist, clone); + std::vector<Inkscape::XML::Node*> templist; + templist.push_back(clone); // add the new clone to the top of the original's parent gchar const *mask_id = SPClipPath::create(templist, doc, &maskTransform); - g_slist_free(templist); outer->setAttribute("clip-path", g_strdup_printf("url(#%s)", mask_id)); @@ -3851,9 +3864,9 @@ void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_ selection->clear(); // create a list of duplicates - GSList *mask_items = NULL; - GSList *apply_to_items = NULL; - GSList *items_to_delete = NULL; + std::vector<Inkscape::XML::Node*> mask_items; + std::vector<SPItem*> apply_to_items; + std::vector<SPItem*> items_to_delete; std::vector<SPItem*> items_to_select; Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -3863,54 +3876,36 @@ void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_ if (apply_to_layer) { // all selected items are used for mask, which is applied to a layer - apply_to_items = g_slist_prepend(apply_to_items, desktop->currentLayer()); + apply_to_items.push_back(SP_ITEM(desktop->currentLayer())); + } + + for (std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++) { + if((!topmost && !apply_to_layer && *i == items.front()) + || (topmost && !apply_to_layer && *i == items.back()) + || apply_to_layer){ - for (std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++) { + Geom::Affine oldtr=(*i)->transform; + (*i)->doWriteTransform((*i)->getRepr(), (*i)->i2doc_affine()); Inkscape::XML::Node *dup = (*i)->getRepr()->duplicate(xml_doc); - mask_items = g_slist_prepend(mask_items, dup); + (*i)->doWriteTransform((*i)->getRepr(), oldtr); + mask_items.push_back(dup); - SPObject *item = *i; if (remove_original) { - items_to_delete = g_slist_prepend(items_to_delete, item); + items_to_delete.push_back(*i); } else { - items_to_select.push_back((SPItem*)item); + items_to_select.push_back(*i); } - } - } else if (!topmost) { - // topmost item is used as a mask, which is applied to other items in a selection - Inkscape::XML::Node *dup = items[0]->getRepr()->duplicate(xml_doc); - mask_items = g_slist_prepend(mask_items, dup); - - if (remove_original) { - SPObject *item = items.front(); - items_to_delete = g_slist_prepend(items_to_delete, item); - } - - for (std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++) { - if(i==items.begin())continue; - apply_to_items = g_slist_prepend(apply_to_items, *i); + continue; + }else{ + apply_to_items.push_back(*i); items_to_select.push_back(*i); } - } else { - SPItem *i = NULL; - for (std::vector<SPItem*>::const_iterator j=items.begin();j!=items.end();j++) { - i=*j; - apply_to_items = g_slist_prepend(apply_to_items, i); - items_to_select.push_back(i); - } - - Inkscape::XML::Node *dup = SP_OBJECT(i)->getRepr()->duplicate(xml_doc); - mask_items = g_slist_prepend(mask_items, dup); - - if (remove_original) { - SPObject *item = reinterpret_cast<SPObject*>(i); - items_to_delete = g_slist_prepend(items_to_delete, item); - } } + items.clear(); - if (apply_to_items && grouping == PREFS_MASKOBJECT_GROUPING_ALL) { + if (grouping == PREFS_MASKOBJECT_GROUPING_ALL) { // group all those objects into one group // and apply mask to that Inkscape::XML::Node *group = xml_doc->createElement("svg:g"); @@ -3919,48 +3914,35 @@ void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_ group->setAttribute("inkscape:groupmode", "maskhelper"); std::vector<Inkscape::XML::Node*> reprs_to_group; - - for (GSList *i = apply_to_items ; NULL != i ; i = i->next) { - reprs_to_group.push_back(static_cast<SPObject*>(i->data)->getRepr()); - items_to_select.erase(remove(items_to_select.begin(), items_to_select.end(), static_cast<SPObject*>(i->data)), items_to_select.end()); + for (std::vector<SPItem*>::const_iterator i = apply_to_items.begin(); i != apply_to_items.end(); i++) { + reprs_to_group.push_back(static_cast<SPObject*>(*i)->getRepr()); } + items_to_select.clear(); sp_selection_group_impl(reprs_to_group, group, xml_doc, doc); // apply clip/mask only to newly created group - g_slist_free(apply_to_items); - apply_to_items = NULL; - apply_to_items = g_slist_prepend(apply_to_items, doc->getObjectByRepr(group)); + apply_to_items.clear(); + apply_to_items.push_back(dynamic_cast<SPItem*>(doc->getObjectByRepr(group))); items_to_select.push_back((SPItem*)(doc->getObjectByRepr(group))); Inkscape::GC::release(group); } + if (grouping == PREFS_MASKOBJECT_GROUPING_SEPARATE) { + items_to_select.clear(); + } + gchar const *attributeName = apply_clip_path ? "clip-path" : "mask"; - for (GSList *i = apply_to_items; NULL != i; i = i->next) { - SPItem *item = reinterpret_cast<SPItem *>(i->data); + for (std::vector<SPItem*>::const_reverse_iterator i = apply_to_items.rbegin(); i != apply_to_items.rend(); i++) { + SPItem *item = reinterpret_cast<SPItem *>(*i); // inverted object transform should be applied to a mask object, // as mask is calculated in user space (after applying transform) - Geom::Affine maskTransform(item->transform.inverse()); - - GSList *mask_items_dup = NULL; - for (GSList *mask_item = mask_items; NULL != mask_item; mask_item = mask_item->next) { - Inkscape::XML::Node *dup = reinterpret_cast<Inkscape::XML::Node *>(mask_item->data)->duplicate(xml_doc); - mask_items_dup = g_slist_prepend(mask_items_dup, dup); - } - - gchar const *mask_id = NULL; - if (apply_clip_path) { - mask_id = SPClipPath::create(mask_items_dup, doc, &maskTransform); - } else { - mask_id = sp_mask_create(mask_items_dup, doc, &maskTransform); - } - - g_slist_free(mask_items_dup); - mask_items_dup = NULL; - - Inkscape::XML::Node *current = SP_OBJECT(i->data)->getRepr(); + std::vector<Inkscape::XML::Node*> mask_items_dup; + for(std::vector<Inkscape::XML::Node*>::const_iterator it=mask_items.begin();it!=mask_items.end();it++) + mask_items_dup.push_back((*it)->duplicate(xml_doc)); + Inkscape::XML::Node *current = SP_OBJECT(*i)->getRepr(); // Node to apply mask to Inkscape::XML::Node *apply_mask_to = current; @@ -3972,7 +3954,6 @@ void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_ Inkscape::XML::Node *spnew = current->duplicate(xml_doc); gint position = current->position(); - items_to_select.erase(remove(items_to_select.begin(), items_to_select.end(), item), items_to_select.end()); current->parent()->appendChild(group); sp_repr_unparent(current); group->appendChild(spnew); @@ -3981,24 +3962,29 @@ void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_ // Apply clip/mask to group instead apply_mask_to = group; - items_to_select.push_back((SPItem*)(doc->getObjectByRepr(group))); + items_to_select.push_back(item = (SPItem*)(doc->getObjectByRepr(group))); Inkscape::GC::release(spnew); Inkscape::GC::release(group); } + Geom::Affine maskTransform(item->i2doc_affine().inverse()); + + gchar const *mask_id = NULL; + if (apply_clip_path) { + mask_id = SPClipPath::create(mask_items_dup, doc, &maskTransform); + } else { + mask_id = sp_mask_create(mask_items_dup, doc, &maskTransform); + } + apply_mask_to->setAttribute(attributeName, Glib::ustring("url(#") + mask_id + ')'); } - g_slist_free(mask_items); - g_slist_free(apply_to_items); - - for (GSList *i = items_to_delete; NULL != i; i = i->next) { - SPObject *item = reinterpret_cast<SPObject*>(i->data); + for (std::vector<SPItem*>::const_iterator i = items_to_delete.begin(); i != items_to_delete.end(); i++) { + SPObject *item = reinterpret_cast<SPObject*>(*i); item->deleteObject(false); items_to_select.erase(remove(items_to_select.begin(), items_to_select.end(), item), items_to_select.end()); } - g_slist_free(items_to_delete); selection->addList(items_to_select); diff --git a/src/selection-chemistry.h b/src/selection-chemistry.h index 8bcab664b..5bcc5b1ea 100644 --- a/src/selection-chemistry.h +++ b/src/selection-chemistry.h @@ -52,7 +52,7 @@ namespace LivePathEffect { } // namespace Inkscape void sp_selection_delete(SPDesktop *desktop); -void sp_selection_duplicate(SPDesktop *desktop, bool suppressDone = false); +void sp_selection_duplicate(SPDesktop *desktop, bool suppressDone = false, bool duplicateLayer = false); void sp_edit_clear_all(Inkscape::Selection *selection); void sp_edit_select_all(SPDesktop *desktop); diff --git a/src/selection.cpp b/src/selection.cpp index 7979b5d61..77a507eec 100644 --- a/src/selection.cpp +++ b/src/selection.cpp @@ -125,6 +125,7 @@ Selection::_releaseContext(SPObject *obj) void Selection::_invalidateCachedLists() { _items.clear(); _reprs.clear(); + _objs_vector.clear(); } void Selection::_clear() { diff --git a/src/sp-clippath.cpp b/src/sp-clippath.cpp index 3c6167438..d66508eae 100644 --- a/src/sp-clippath.cpp +++ b/src/sp-clippath.cpp @@ -296,7 +296,7 @@ sp_clippath_view_list_remove(SPClipPathView *list, SPClipPathView *view) } // Create a mask element (using passed elements), add it to <defs> -const gchar *SPClipPath::create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform) +const gchar *SPClipPath::create (std::vector<Inkscape::XML::Node*> &reprs, SPDocument *document, Geom::Affine const* applyTransform) { Inkscape::XML::Node *defsrepr = document->getDefs()->getRepr(); @@ -308,13 +308,12 @@ const gchar *SPClipPath::create (GSList *reprs, SPDocument *document, Geom::Affi const gchar *id = repr->attribute("id"); SPObject *clip_path_object = document->getObjectById(id); - for (GSList *it = reprs; it != NULL; it = it->next) { - Inkscape::XML::Node *node = (Inkscape::XML::Node *)(it->data); + for (std::vector<Inkscape::XML::Node*>::const_iterator it = reprs.begin(); it != reprs.end(); it++) { + Inkscape::XML::Node *node = (*it); SPItem *item = SP_ITEM(clip_path_object->appendChildRepr(node)); if (NULL != applyTransform) { - Geom::Affine transform (item->transform); - transform *= (*applyTransform); + Geom::Affine transform (item->transform * (*applyTransform)); item->doWriteTransform(item->getRepr(), transform); } } diff --git a/src/sp-clippath.h b/src/sp-clippath.h index eb8b14174..91dcfd625 100644 --- a/src/sp-clippath.h +++ b/src/sp-clippath.h @@ -45,7 +45,7 @@ public: unsigned int clipPathUnits : 1; SPClipPathView *display; - static char const *create(GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform); + static char const *create(std::vector<Inkscape::XML::Node*> &reprs, SPDocument *document, Geom::Affine const* applyTransform); //static GType sp_clippath_get_type(void); Inkscape::DrawingItem *show(Inkscape::Drawing &drawing, unsigned int key); diff --git a/src/sp-item.cpp b/src/sp-item.cpp index 8c99e9bcf..410fd9b37 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -349,17 +349,11 @@ void SPItem::lowerToBottom() { using Inkscape::Util::MutableList; using Inkscape::Util::reverse_list; - MutableList<SPObject &> bottom=find_last_if( - reverse_list<SPObject::SiblingIterator>( - parent->firstChild(), this - ), - MutableList<SPObject &>(), - &is_item - ); + SPObject * bottom=parent->firstChild(); + while(dynamic_cast<SPObject*>(bottom) && dynamic_cast<SPObject*>(bottom->next) && bottom!=this && !is_item(*(bottom->next))) bottom=bottom->next; if (bottom) { - ++bottom; Inkscape::XML::Node *ref = ( bottom ? bottom->getRepr() : NULL ); - getRepr()->parent()->changeOrder(getRepr(), ref); + parent->getRepr()->changeOrder(getRepr(), ref); } } @@ -367,20 +361,20 @@ void SPItem::moveTo(SPItem *target, bool intoafter) { Inkscape::XML::Node *target_ref = ( target ? target->getRepr() : NULL ); Inkscape::XML::Node *our_ref = getRepr(); - gboolean first = FALSE; - - if (target_ref == our_ref) { - // Move to ourself ignore - return; - } if (!target_ref) { // Assume move to the "first" in the top node, find the top node - target_ref = our_ref; - while (target_ref->parent() != target_ref->root()) { - target_ref = target_ref->parent(); + intoafter = false; + SPObject* bottom = this->document->getObjectByRepr(our_ref->root())->firstChild(); + while(!dynamic_cast<SPItem*>(bottom->next)){ + bottom=bottom->next; } - first = TRUE; + target_ref = bottom->getRepr(); + } + + if (target_ref == our_ref) { + // Move to ourself ignore + return; } if (intoafter) { @@ -391,16 +385,10 @@ void SPItem::moveTo(SPItem *target, bool intoafter) { // Change in parent, need to remove and add our_ref->parent()->removeChild(our_ref); target_ref->parent()->addChild(our_ref, target_ref); - } else if (!first) { + } else { // Same parent, just move our_ref->parent()->changeOrder(our_ref, target_ref); } - - if (first && parent) { - // If "first" ensure it appears after the defs etc - lowerToBottom(); - return; - } } void SPItem::build(SPDocument *document, Inkscape::XML::Node *repr) { @@ -1234,8 +1222,8 @@ void SPItem::adjust_pattern(Geom::Affine const &postmul, bool set, PatternTransf SPObject *server = style->getFillPaintServer(); SPPattern *serverPatt = dynamic_cast<SPPattern *>(server); if ( serverPatt ) { - SPPattern *pattern = sp_pattern_clone_if_necessary(this, serverPatt, "fill"); - sp_pattern_transform_multiply(pattern, postmul, set); + SPPattern *pattern = serverPatt->clone_if_necessary(this, "fill"); + pattern->transform_multiply(postmul, set); } } @@ -1244,8 +1232,8 @@ void SPItem::adjust_pattern(Geom::Affine const &postmul, bool set, PatternTransf SPObject *server = style->getStrokePaintServer(); SPPattern *serverPatt = dynamic_cast<SPPattern *>(server); if ( serverPatt ) { - SPPattern *pattern = sp_pattern_clone_if_necessary(this, serverPatt, "stroke"); - sp_pattern_transform_multiply(pattern, postmul, set); + SPPattern *pattern = serverPatt->clone_if_necessary(this, "stroke"); + pattern->transform_multiply(postmul, set); } } } diff --git a/src/sp-mask.cpp b/src/sp-mask.cpp index d60473e1d..f8fb7aff4 100644 --- a/src/sp-mask.cpp +++ b/src/sp-mask.cpp @@ -209,7 +209,7 @@ Inkscape::XML::Node* SPMask::write(Inkscape::XML::Document* xml_doc, Inkscape::X // Create a mask element (using passed elements), add it to <defs> const gchar * -sp_mask_create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform) +sp_mask_create (std::vector<Inkscape::XML::Node*> &reprs, SPDocument *document, Geom::Affine const* applyTransform) { Inkscape::XML::Node *defsrepr = document->getDefs()->getRepr(); @@ -221,13 +221,12 @@ sp_mask_create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTr const gchar *mask_id = repr->attribute("id"); SPObject *mask_object = document->getObjectById(mask_id); - for (GSList *it = reprs; it != NULL; it = it->next) { - Inkscape::XML::Node *node = (Inkscape::XML::Node *)(it->data); + for (std::vector<Inkscape::XML::Node*>::const_iterator it = reprs.begin(); it != reprs.end(); it++) { + Inkscape::XML::Node *node = (*it); SPItem *item = SP_ITEM(mask_object->appendChildRepr(node)); if (NULL != applyTransform) { - Geom::Affine transform (item->transform); - transform *= (*applyTransform); + Geom::Affine transform (item->transform * (*applyTransform)); item->doWriteTransform(item->getRepr(), transform); } } diff --git a/src/sp-mask.h b/src/sp-mask.h index e991fedb6..3559483bb 100644 --- a/src/sp-mask.h +++ b/src/sp-mask.h @@ -108,6 +108,6 @@ protected: } }; -const char *sp_mask_create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform); +const char *sp_mask_create (std::vector<Inkscape::XML::Node*> &reprs, SPDocument *document, Geom::Affine const* applyTransform); #endif // SEEN_SP_MASK_H diff --git a/src/sp-offset.cpp b/src/sp-offset.cpp index c5336955c..7c3d0bd03 100644 --- a/src/sp-offset.cpp +++ b/src/sp-offset.cpp @@ -83,7 +83,7 @@ static void sp_offset_source_modified (SPObject *iSource, guint flags, SPItem *i // fast is not mathematically correct, because computing the offset of a single // cubic bezier patch is not trivial; in particular, there are problems with holes // reappearing in offset when the radius becomes too large -static bool use_slow_but_correct_offset_method=false; +static bool use_slow_but_correct_offset_method=true; SPOffset::SPOffset() : SPShape() { this->rad = 1.0; diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index e89ed77ba..755d3d162 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -5,7 +5,7 @@ * Lauris Kaplinski <lauris@kaplinski.com> * bulia byak <buliabyak@users.sf.net> * Jon A. Cruz <jon@joncruz.org> - * Abhishek Sharma + * Abhishek Sharma * * Copyright (C) 2002 Lauris Kaplinski * @@ -13,15 +13,15 @@ */ #ifdef HAVE_CONFIG_H -# include "config.h" +#include "config.h" #endif #include <cstring> #include <string> #include <glibmm.h> #include <2geom/transforms.h> +#include <sigc++/functors/mem_fun.h> -#include "macros.h" #include "svg/svg.h" #include "display/cairo-utils.h" #include "display/drawing-context.h" @@ -34,67 +34,61 @@ #include "style.h" #include "sp-pattern.h" #include "xml/repr.h" -#include "display/grayscale.h" -#include <sigc++/functors/ptr_fun.h> -#include <sigc++/adaptors/bind.h> +#include "sp-factory.h" -/* - * Pattern - */ -static void pattern_ref_changed(SPObject *old_ref, SPObject *ref, SPPattern *pat); -static void pattern_ref_modified (SPObject *ref, guint flags, SPPattern *pattern); - -SPPattern::SPPattern() : SPPaintServer(), SPViewBox() { - this->href = NULL; - - this->ref = new SPPatternReference(this); - this->ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(pattern_ref_changed), this)); +SPPattern::SPPattern() + : SPPaintServer() + , SPViewBox() +{ + this->ref = new SPPatternReference(this); + this->ref->changedSignal().connect(sigc::mem_fun(this, &SPPattern::_onRefChanged)); - this->patternUnits = SP_PATTERN_UNITS_OBJECTBOUNDINGBOX; - this->patternUnits_set = FALSE; + this->_pattern_units = UNITS_OBJECTBOUNDINGBOX; + this->_pattern_units_set = false; - this->patternContentUnits = SP_PATTERN_UNITS_USERSPACEONUSE; - this->patternContentUnits_set = FALSE; + this->_pattern_content_units = UNITS_USERSPACEONUSE; + this->_pattern_content_units_set = false; - this->patternTransform = Geom::identity(); - this->patternTransform_set = FALSE; + this->_pattern_transform = Geom::identity(); + this->_pattern_transform_set = false; - this->x.unset(); - this->y.unset(); - this->width.unset(); - this->height.unset(); + this->_x.unset(); + this->_y.unset(); + this->_width.unset(); + this->_height.unset(); } -SPPattern::~SPPattern() { -} +SPPattern::~SPPattern() {} -void SPPattern::build(SPDocument* doc, Inkscape::XML::Node* repr) { - SPPaintServer::build(doc, repr); - - this->readAttr( "patternUnits" ); - this->readAttr( "patternContentUnits" ); - this->readAttr( "patternTransform" ); - this->readAttr( "x" ); - this->readAttr( "y" ); - this->readAttr( "width" ); - this->readAttr( "height" ); - this->readAttr( "viewBox" ); - this->readAttr( "preserveAspectRatio" ); - this->readAttr( "xlink:href" ); - - /* Register ourselves */ - doc->addResource("pattern", this); +void SPPattern::build(SPDocument *doc, Inkscape::XML::Node *repr) +{ + SPPaintServer::build(doc, repr); + + this->readAttr("patternUnits"); + this->readAttr("patternContentUnits"); + this->readAttr("patternTransform"); + this->readAttr("x"); + this->readAttr("y"); + this->readAttr("width"); + this->readAttr("height"); + this->readAttr("viewBox"); + this->readAttr("preserveAspectRatio"); + this->readAttr("xlink:href"); + + /* Register ourselves */ + doc->addResource("pattern", this); } -void SPPattern::release() { +void SPPattern::release() +{ if (this->document) { // Unregister ourselves this->document->removeResource("pattern", this); } if (this->ref) { - this->modified_connection.disconnect(); + this->_modified_connection.disconnect(); this->ref->detach(); delete this->ref; this->ref = NULL; @@ -103,113 +97,121 @@ void SPPattern::release() { SPPaintServer::release(); } -void SPPattern::set(unsigned int key, const gchar* value) { - switch (key) { - case SP_ATTR_PATTERNUNITS: - if (value) { - if (!strcmp (value, "userSpaceOnUse")) { - this->patternUnits = SP_PATTERN_UNITS_USERSPACEONUSE; - } else { - this->patternUnits = SP_PATTERN_UNITS_OBJECTBOUNDINGBOX; - } - - this->patternUnits_set = TRUE; - } else { - this->patternUnits_set = FALSE; - } - - this->requestModified(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_PATTERNCONTENTUNITS: - if (value) { - if (!strcmp (value, "userSpaceOnUse")) { - this->patternContentUnits = SP_PATTERN_UNITS_USERSPACEONUSE; - } else { - this->patternContentUnits = SP_PATTERN_UNITS_OBJECTBOUNDINGBOX; - } - - this->patternContentUnits_set = TRUE; - } else { - this->patternContentUnits_set = FALSE; - } - - this->requestModified(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_PATTERNTRANSFORM: { - Geom::Affine t; - - if (value && sp_svg_transform_read (value, &t)) { - this->patternTransform = t; - this->patternTransform_set = TRUE; - } else { - this->patternTransform = Geom::identity(); - this->patternTransform_set = FALSE; - } - - this->requestModified(SP_OBJECT_MODIFIED_FLAG); - break; - } - case SP_ATTR_X: - this->x.readOrUnset(value); - this->requestModified(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_Y: - this->y.readOrUnset(value); - this->requestModified(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_WIDTH: - this->width.readOrUnset(value); - this->requestModified(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_HEIGHT: - this->height.readOrUnset(value); - this->requestModified(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_VIEWBOX: - set_viewBox( value ); +void SPPattern::set(unsigned int key, const gchar *value) +{ + switch (key) { + case SP_ATTR_PATTERNUNITS: + if (value) { + if (!strcmp(value, "userSpaceOnUse")) { + this->_pattern_units = UNITS_USERSPACEONUSE; + } + else { + this->_pattern_units = UNITS_OBJECTBOUNDINGBOX; + } + + this->_pattern_units_set = true; + } + else { + this->_pattern_units_set = false; + } + + this->requestModified(SP_OBJECT_MODIFIED_FLAG); + break; + + case SP_ATTR_PATTERNCONTENTUNITS: + if (value) { + if (!strcmp(value, "userSpaceOnUse")) { + this->_pattern_content_units = UNITS_USERSPACEONUSE; + } + else { + this->_pattern_content_units = UNITS_OBJECTBOUNDINGBOX; + } + + this->_pattern_content_units_set = true; + } + else { + this->_pattern_content_units_set = false; + } + + this->requestModified(SP_OBJECT_MODIFIED_FLAG); + break; + + case SP_ATTR_PATTERNTRANSFORM: { + Geom::Affine t; + + if (value && sp_svg_transform_read(value, &t)) { + this->_pattern_transform = t; + this->_pattern_transform_set = true; + } + else { + this->_pattern_transform = Geom::identity(); + this->_pattern_transform_set = false; + } + + this->requestModified(SP_OBJECT_MODIFIED_FLAG); + break; + } + case SP_ATTR_X: + this->_x.readOrUnset(value); + this->requestModified(SP_OBJECT_MODIFIED_FLAG); + break; + + case SP_ATTR_Y: + this->_y.readOrUnset(value); + this->requestModified(SP_OBJECT_MODIFIED_FLAG); + break; + + case SP_ATTR_WIDTH: + this->_width.readOrUnset(value); + this->requestModified(SP_OBJECT_MODIFIED_FLAG); + break; + + case SP_ATTR_HEIGHT: + this->_height.readOrUnset(value); + this->requestModified(SP_OBJECT_MODIFIED_FLAG); + break; + + case SP_ATTR_VIEWBOX: + set_viewBox(value); this->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG); break; case SP_ATTR_PRESERVEASPECTRATIO: - set_preserveAspectRatio( value ); + set_preserveAspectRatio(value); this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG); break; - case SP_ATTR_XLINK_HREF: - if ( value && this->href && ( strcmp(value, this->href) == 0 ) ) { - /* Href unchanged, do nothing. */ - } else { - g_free(this->href); - this->href = NULL; - - if (value) { - // First, set the href field; it's only used in the "unchanged" check above. - this->href = g_strdup(value); - // Now do the attaching, which emits the changed signal. - if (value) { - try { - this->ref->attach(Inkscape::URI(value)); - } catch (Inkscape::BadURIException &e) { - g_warning("%s", e.what()); - this->ref->detach(); - } - } else { - this->ref->detach(); - } - } - } - break; - - default: - SPPaintServer::set(key, value); - break; - } + case SP_ATTR_XLINK_HREF: + if (value && this->href == value) { + /* Href unchanged, do nothing. */ + } + else { + this->href.clear(); + + if (value) { + // First, set the href field; it's only used in the "unchanged" check above. + this->href = value; + // Now do the attaching, which emits the changed signal. + if (value) { + try { + this->ref->attach(Inkscape::URI(value)); + } + catch (Inkscape::BadURIException &e) { + g_warning("%s", e.what()); + this->ref->detach(); + } + } + else { + this->ref->detach(); + } + } + } + break; + + default: + SPPaintServer::set(key, value); + break; + } } @@ -217,104 +219,90 @@ void SPPattern::set(unsigned int key, const gchar* value) { /* fixme: We need ::order_changed handler too (Lauris) */ -static GSList *pattern_getchildren(SPPattern *pat) +void SPPattern::_getChildren(std::list<SPObject *> &l) { - GSList *l = NULL; - - for (SPPattern *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + for (SPPattern *pat_i = this; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { if (pat_i->firstChild()) { // find the first one with children - for (SPObject *child = pat->firstChild() ; child ; child = child->getNext() ) { - l = g_slist_prepend (l, child); - } - break; // do not go further up the chain if children are found + for (SPObject *child = pat_i->firstChild(); child; child = child->getNext()) { + l.push_back(child); + } + break; // do not go further up the chain if children are found } } - - return l; } -void SPPattern::update(SPCtx* ctx, unsigned int flags) { - if (flags & SP_OBJECT_MODIFIED_FLAG) { - flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; - } +void SPPattern::update(SPCtx *ctx, unsigned int flags) +{ + typedef std::list<SPObject *>::iterator SPObjectIterator; + + if (flags & SP_OBJECT_MODIFIED_FLAG) { + flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; + } - flags &= SP_OBJECT_MODIFIED_CASCADE; + flags &= SP_OBJECT_MODIFIED_CASCADE; - GSList *l = pattern_getchildren (this); - l = g_slist_reverse (l); + std::list<SPObject *> l; + _getChildren(l); - while (l) { - SPObject *child = SP_OBJECT (l->data); + for (SPObjectIterator it = l.begin(); it != l.end(); it++) { + SPObject *child = *it; - sp_object_ref (child, NULL); - l = g_slist_remove (l, child); + sp_object_ref(child, NULL); - if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { - child->updateDisplay(ctx, flags); - } + if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { + child->updateDisplay(ctx, flags); + } - sp_object_unref (child, NULL); - } + sp_object_unref(child, NULL); + } } -void SPPattern::modified(unsigned int flags) { - if (flags & SP_OBJECT_MODIFIED_FLAG) { - flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; - } +void SPPattern::modified(unsigned int flags) +{ + typedef std::list<SPObject *>::iterator SPObjectIterator; + + if (flags & SP_OBJECT_MODIFIED_FLAG) { + flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; + } - flags &= SP_OBJECT_MODIFIED_CASCADE; + flags &= SP_OBJECT_MODIFIED_CASCADE; - GSList *l = pattern_getchildren (this); - l = g_slist_reverse (l); + std::list<SPObject *> l; + _getChildren(l); - while (l) { - SPObject *child = SP_OBJECT (l->data); + for (SPObjectIterator it = l.begin(); it != l.end(); it++) { + SPObject *child = *it; - sp_object_ref (child, NULL); - l = g_slist_remove (l, child); + sp_object_ref(child, NULL); - if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { - child->emitModified(flags); - } + if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { + child->emitModified(flags); + } - sp_object_unref (child, NULL); - } + sp_object_unref(child, NULL); + } } -/** -Gets called when the pattern is reattached to another <pattern> -*/ -static void -pattern_ref_changed(SPObject *old_ref, SPObject *ref, SPPattern *pat) +void SPPattern::_onRefChanged(SPObject *old_ref, SPObject *ref) { - if (old_ref) { - pat->modified_connection.disconnect(); - } + if (old_ref) { + _modified_connection.disconnect(); + } - if (SP_IS_PATTERN (ref)) { - pat->modified_connection = ref->connectModified(sigc::bind<2>(sigc::ptr_fun(&pattern_ref_modified), pat)); - } + if (SP_IS_PATTERN(ref)) { + _modified_connection = ref->connectModified(sigc::mem_fun(this, &SPPattern::_onRefModified)); + } - pattern_ref_modified (ref, 0, pat); + _onRefModified(ref, 0); } -/** -Gets called when the referenced <pattern> is changed -*/ -static void pattern_ref_modified (SPObject */*ref*/, guint /*flags*/, SPPattern *pattern) +void SPPattern::_onRefModified(SPObject * /*ref*/, guint /*flags*/) { - if ( SP_IS_OBJECT(pattern) ) { - pattern->requestModified(SP_OBJECT_MODIFIED_FLAG); - } + requestModified(SP_OBJECT_MODIFIED_FLAG); // Conditional to avoid causing infinite loop if there's a cycle in the href chain. } - -/** -Count how many times pat is used by the styles of o and its descendants -*/ -static guint -count_pattern_hrefs(SPObject *o, SPPattern *pat) +guint SPPattern::_countHrefs(SPObject *o) const { if (!o) return 1; @@ -322,84 +310,79 @@ count_pattern_hrefs(SPObject *o, SPPattern *pat) guint i = 0; SPStyle *style = o->style; - if (style - && style->fill.isPaintserver() - && SP_IS_PATTERN(SP_STYLE_FILL_SERVER(style)) - && SP_PATTERN(SP_STYLE_FILL_SERVER(style)) == pat) - { - i ++; + if (style && style->fill.isPaintserver() && SP_IS_PATTERN(SP_STYLE_FILL_SERVER(style)) && + SP_PATTERN(SP_STYLE_FILL_SERVER(style)) == this) { + i++; } - if (style - && style->stroke.isPaintserver() - && SP_IS_PATTERN(SP_STYLE_STROKE_SERVER(style)) - && SP_PATTERN(SP_STYLE_STROKE_SERVER(style)) == pat) - { - i ++; + if (style && style->stroke.isPaintserver() && SP_IS_PATTERN(SP_STYLE_STROKE_SERVER(style)) && + SP_PATTERN(SP_STYLE_STROKE_SERVER(style)) == this) { + i++; } - for ( SPObject *child = o->firstChild(); child != NULL; child = child->next ) { - i += count_pattern_hrefs(child, pat); + for (SPObject *child = o->firstChild(); child != NULL; child = child->next) { + i += _countHrefs(child); } return i; } -SPPattern *pattern_chain(SPPattern *pattern) +SPPattern *SPPattern::_chain() const { - SPDocument *document = pattern->document; - Inkscape::XML::Document *xml_doc = document->getReprDoc(); + Inkscape::XML::Document *xml_doc = document->getReprDoc(); Inkscape::XML::Node *defsrepr = document->getDefs()->getRepr(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:pattern"); repr->setAttribute("inkscape:collect", "always"); - gchar *parent_ref = g_strconcat("#", pattern->getRepr()->attribute("id"), NULL); - repr->setAttribute("xlink:href", parent_ref); - g_free (parent_ref); + Glib::ustring parent_ref = Glib::ustring::compose("#%1", getRepr()->attribute("id")); + repr->setAttribute("xlink:href", parent_ref); defsrepr->addChild(repr, NULL); const gchar *child_id = repr->attribute("id"); SPObject *child = document->getObjectById(child_id); - g_assert (SP_IS_PATTERN (child)); + g_assert(SP_IS_PATTERN(child)); - return SP_PATTERN (child); + return SP_PATTERN(child); } -SPPattern * -sp_pattern_clone_if_necessary (SPItem *item, SPPattern *pattern, const gchar *property) +SPPattern *SPPattern::clone_if_necessary(SPItem *item, const gchar *property) { - if (!pattern->href || pattern->hrefcount > count_pattern_hrefs(item, pattern)) { - pattern = pattern_chain (pattern); - gchar *href = g_strconcat("url(#", pattern->getRepr()->attribute("id"), ")", NULL); + SPPattern *pattern = this; + if (pattern->href.empty() || pattern->hrefcount > _countHrefs(item)) { + pattern = _chain(); + Glib::ustring href = Glib::ustring::compose("url(#%1)", pattern->getRepr()->attribute("id")); - SPCSSAttr *css = sp_repr_css_attr_new (); - sp_repr_css_set_property (css, property, href); + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property(css, property, href.c_str()); sp_repr_css_change_recursive(item->getRepr(), css, "style"); } return pattern; } -void -sp_pattern_transform_multiply (SPPattern *pattern, Geom::Affine postmul, bool set) +void SPPattern::transform_multiply(Geom::Affine postmul, bool set) { // this formula is for a different interpretation of pattern transforms as described in (*) in sp-pattern.cpp // for it to work, we also need sp_object_read_attr( item, "transform"); - //pattern->patternTransform = premul * item->transform * pattern->patternTransform * item->transform.inverse() * postmul; + // pattern->patternTransform = premul * item->transform * pattern->patternTransform * item->transform.inverse() * + // postmul; // otherwise the formula is much simpler if (set) { - pattern->patternTransform = postmul; - } else { - pattern->patternTransform = pattern_patternTransform(pattern) * postmul; + _pattern_transform = postmul; } - pattern->patternTransform_set = TRUE; + else { + _pattern_transform = getTransform() * postmul; + } + _pattern_transform_set = true; - gchar *c=sp_svg_transform_write(pattern->patternTransform); - pattern->getRepr()->setAttribute("patternTransform", c); - g_free(c); + Glib::ustring c = sp_svg_transform_write(_pattern_transform); + getRepr()->setAttribute("patternTransform", c); } -const gchar *pattern_tile(const std::vector<Inkscape::XML::Node*> &reprs, Geom::Rect bounds, SPDocument *document, Geom::Affine transform, Geom::Affine move) +const gchar *SPPattern::produce(const std::vector<Inkscape::XML::Node *> &reprs, Geom::Rect bounds, + SPDocument *document, Geom::Affine transform, Geom::Affine move) { + typedef std::vector<Inkscape::XML::Node *>::const_iterator NodePtrIterator; + Inkscape::XML::Document *xml_doc = document->getReprDoc(); Inkscape::XML::Node *defsrepr = document->getDefs()->getRepr(); @@ -408,20 +391,19 @@ const gchar *pattern_tile(const std::vector<Inkscape::XML::Node*> &reprs, Geom:: sp_repr_set_svg_double(repr, "width", bounds.dimensions()[Geom::X]); sp_repr_set_svg_double(repr, "height", bounds.dimensions()[Geom::Y]); - gchar *t=sp_svg_transform_write(transform); + Glib::ustring t = sp_svg_transform_write(transform); repr->setAttribute("patternTransform", t); - g_free(t); defsrepr->appendChild(repr); const gchar *pat_id = repr->attribute("id"); SPObject *pat_object = document->getObjectById(pat_id); - for (std::vector<Inkscape::XML::Node*>::const_iterator i=reprs.begin();i!=reprs.end();i++){ + for (NodePtrIterator i = reprs.begin(); i != reprs.end(); i++) { Inkscape::XML::Node *node = *i; SPItem *copy = SP_ITEM(pat_object->appendChildRepr(node)); Geom::Affine dup_transform; - if (!sp_svg_transform_read (node->attribute("transform"), &dup_transform)) + if (!sp_svg_transform_read(node->attribute("transform"), &dup_transform)) dup_transform = Geom::identity(); dup_transform *= move; @@ -432,14 +414,15 @@ const gchar *pattern_tile(const std::vector<Inkscape::XML::Node*> &reprs, Geom:: return pat_id; } -SPPattern *pattern_getroot(SPPattern *pat) +SPPattern *SPPattern::rootPattern() { - for (SPPattern *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { - if ( pat_i->firstChild() ) { // find the first one with children + for (SPPattern *pat_i = this; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + if (pat_i->firstChild()) { // find the first one with children return pat_i; } } - return pat; // document is broken, we can't get to root; but at least we can return pat which is supposedly a valid pattern + return this; // document is broken, we can't get to root; but at least we can return pat which is supposedly a valid + // pattern } @@ -447,73 +430,73 @@ SPPattern *pattern_getroot(SPPattern *pat) // Access functions that look up fields up the chain of referenced patterns and return the first one which is set // FIXME: all of them must use chase_hrefs the same as in SPGradient, to avoid lockup on circular refs -guint pattern_patternUnits (SPPattern const *pat) +SPPattern::PatternUnits SPPattern::patternUnits() const { - for (SPPattern const *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { - if (pat_i->patternUnits_set) - return pat_i->patternUnits; + for (SPPattern const *pat_i = this; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + if (pat_i->_pattern_units_set) + return pat_i->_pattern_units; } - return pat->patternUnits; + return _pattern_units; } -guint pattern_patternContentUnits (SPPattern const *pat) +SPPattern::PatternUnits SPPattern::patternContentUnits() const { - for (SPPattern const *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { - if (pat_i->patternContentUnits_set) - return pat_i->patternContentUnits; + for (SPPattern const *pat_i = this; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + if (pat_i->_pattern_content_units_set) + return pat_i->_pattern_content_units; } - return pat->patternContentUnits; + return _pattern_content_units; } -Geom::Affine const &pattern_patternTransform(SPPattern const *pat) +Geom::Affine const &SPPattern::getTransform() const { - for (SPPattern const *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { - if (pat_i->patternTransform_set) - return pat_i->patternTransform; + for (SPPattern const *pat_i = this; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + if (pat_i->_pattern_transform_set) + return pat_i->_pattern_transform; } - return pat->patternTransform; + return _pattern_transform; } -gdouble pattern_x (SPPattern const *pat) +gdouble SPPattern::x() const { - for (SPPattern const *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { - if (pat_i->x._set) - return pat_i->x.computed; + for (SPPattern const *pat_i = this; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + if (pat_i->_x._set) + return pat_i->_x.computed; } return 0; } -gdouble pattern_y (SPPattern const *pat) +gdouble SPPattern::y() const { - for (SPPattern const *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { - if (pat_i->y._set) - return pat_i->y.computed; + for (SPPattern const *pat_i = this; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + if (pat_i->_y._set) + return pat_i->_y.computed; } return 0; } -gdouble pattern_width (SPPattern const* pat) +gdouble SPPattern::width() const { - for (SPPattern const *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { - if (pat_i->width._set) - return pat_i->width.computed; + for (SPPattern const *pat_i = this; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + if (pat_i->_width._set) + return pat_i->_width.computed; } return 0; } -gdouble pattern_height (SPPattern const *pat) +gdouble SPPattern::height() const { - for (SPPattern const *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { - if (pat_i->height._set) - return pat_i->height.computed; + for (SPPattern const *pat_i = this; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + if (pat_i->_height._set) + return pat_i->_height.computed; } return 0; } -Geom::OptRect pattern_viewBox (SPPattern const *pat) +Geom::OptRect SPPattern::viewbox() const { Geom::OptRect viewbox; - for (SPPattern const *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + for (SPPattern const *pat_i = this; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { if (pat_i->viewBox_set) { viewbox = pat_i->viewBox; break; @@ -522,10 +505,10 @@ Geom::OptRect pattern_viewBox (SPPattern const *pat) return viewbox; } -static bool pattern_hasItemChildren (SPPattern const *pat) +bool SPPattern::_hasItemChildren() const { bool hasChildren = false; - for (SPObject const *child = pat->firstChild() ; child && !hasChildren ; child = child->getNext() ) { + for (SPObject const *child = firstChild(); child && !hasChildren; child = child->getNext()) { if (SP_IS_ITEM(child)) { hasChildren = true; } @@ -535,15 +518,16 @@ static bool pattern_hasItemChildren (SPPattern const *pat) bool SPPattern::isValid() const { - double tile_width = pattern_width(this); - double tile_height = pattern_height(this); + double tile_width = width(); + double tile_height = height(); - if (tile_width <= 0 || tile_height <= 0) - return false; - return true; + if (tile_width <= 0 || tile_height <= 0) + return false; + return true; } -cairo_pattern_t* SPPattern::pattern_new(cairo_t *base_ct, Geom::OptRect const &bbox, double opacity) { +cairo_pattern_t *SPPattern::pattern_new(cairo_t *base_ct, Geom::OptRect const &bbox, double opacity) +{ bool needs_opacity = (1.0 - opacity) >= 1e-3; bool visible = opacity >= 1e-3; @@ -557,28 +541,28 @@ cairo_pattern_t* SPPattern::pattern_new(cairo_t *base_ct, Geom::OptRect const &b for (SPPattern *pat_i = this; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { // find the first one with item children - if (pat_i && SP_IS_OBJECT(pat_i) && pattern_hasItemChildren(pat_i)) { + if (pat_i && SP_IS_OBJECT(pat_i) && pat_i->_hasItemChildren()) { shown = pat_i; break; // do not go further up the chain if children are found } } if (!shown) { - return cairo_pattern_create_rgba(0,0,0,0); + return cairo_pattern_create_rgba(0, 0, 0, 0); } /* Create drawing for rendering */ Inkscape::Drawing drawing; - unsigned int dkey = SPItem::display_key_new (1); + unsigned int dkey = SPItem::display_key_new(1); Inkscape::DrawingGroup *root = new Inkscape::DrawingGroup(drawing); drawing.setRoot(root); - for (SPObject *child = shown->firstChild(); child != NULL; child = child->getNext() ) { - if (SP_IS_ITEM (child)) { + for (SPObject *child = shown->firstChild(); child != NULL; child = child->getNext()) { + if (SP_IS_ITEM(child)) { // for each item in pattern, show it on our drawing, add to the group, // and connect to the release signal in case the item gets deleted Inkscape::DrawingItem *cai; - cai = SP_ITEM(child)->invoke_show (drawing, dkey, SP_ITEM_SHOW_DISPLAY); + cai = SP_ITEM(child)->invoke_show(drawing, dkey, SP_ITEM_SHOW_DISPLAY); root->appendChild(cai); } } @@ -591,40 +575,41 @@ cairo_pattern_t* SPPattern::pattern_new(cairo_t *base_ct, Geom::OptRect const &b // * "x", "y", and "patternTransform" transform tile to user space after tile is generated. // These functions recursively search up the tree to find the values. - double tile_x = pattern_x(this); - double tile_y = pattern_y(this); - double tile_width = pattern_width(this); - double tile_height = pattern_height(this); - if ( bbox && (pattern_patternUnits(this) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) ) { - tile_x *= bbox->width(); - tile_y *= bbox->height(); - tile_width *= bbox->width(); + double tile_x = x(); + double tile_y = y(); + double tile_width = width(); + double tile_height = height(); + if (bbox && (patternUnits() == UNITS_OBJECTBOUNDINGBOX)) { + tile_x *= bbox->width(); + tile_y *= bbox->height(); + tile_width *= bbox->width(); tile_height *= bbox->height(); } // Pattern size in pattern space Geom::Rect pattern_tile = Geom::Rect::from_xywh(0, 0, tile_width, tile_height); - + // Content to tile (pattern space) Geom::Affine content2ps; - Geom::OptRect effective_view_box = pattern_viewBox(this); + Geom::OptRect effective_view_box = viewbox(); if (effective_view_box) { - // viewBox to pattern server (using SPViewBox) + // viewBox to pattern server (using SPViewBox) viewBox = *effective_view_box; c2p.setIdentity(); - apply_viewbox( pattern_tile ); + apply_viewbox(pattern_tile); content2ps = c2p; - } else { + } + else { // Content to bbox - if (bbox && (pattern_patternContentUnits(this) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) ) { - content2ps = Geom::Affine(bbox->width(), 0.0, 0.0, bbox->height(), 0,0); + if (bbox && (patternContentUnits() == UNITS_OBJECTBOUNDINGBOX)) { + content2ps = Geom::Affine(bbox->width(), 0.0, 0.0, bbox->height(), 0, 0); } } // Tile (pattern space) to user. - Geom::Affine ps2user = Geom::Translate(tile_x,tile_y) * pattern_patternTransform(this); + Geom::Affine ps2user = Geom::Translate(tile_x, tile_y) * getTransform(); // Transform of object with pattern (includes screen scaling) @@ -644,7 +629,7 @@ cairo_pattern_t* SPPattern::pattern_new(cairo_t *base_ct, Geom::OptRect const &b // to find the optimum tile size for rendering // c is number of pixels in buffer x and y. // Scale factor of 1.1 is too small... see bug #1251039 - Geom::Point c(pattern_tile.dimensions()*ps2user.descrim()*full.descrim()*2.0); + Geom::Point c(pattern_tile.dimensions() * ps2user.descrim() * full.descrim() * 2.0); // Create drawing surface with size of pattern tile (in pattern space) but with number of pixels // based on required resolution (c). @@ -660,16 +645,16 @@ cairo_pattern_t* SPPattern::pattern_new(cairo_t *base_ct, Geom::OptRect const &b } // TODO: make sure there are no leaks. - Inkscape::UpdateContext ctx; // UpdateContext is structure with only ctm! + Inkscape::UpdateContext ctx; // UpdateContext is structure with only ctm! ctx.ctm = content2ps * pattern_surface.drawingTransform(); - dc.transform( pattern_surface.drawingTransform().inverse() ); + dc.transform(pattern_surface.drawingTransform().inverse()); drawing.update(Geom::IntRect::infinite(), ctx); // Render drawing to pattern_surface via drawing context, this calls root->render // which is really DrawingItem->render(). drawing.render(dc, one_tile); - for (SPObject *child = shown->firstChild() ; child != NULL; child = child->getNext() ) { - if (SP_IS_ITEM (child)) { + for (SPObject *child = shown->firstChild(); child != NULL; child = child->getNext()) { + if (SP_IS_ITEM(child)) { SP_ITEM(child)->invoke_hide(dkey); } } @@ -685,12 +670,12 @@ cairo_pattern_t* SPPattern::pattern_new(cairo_t *base_ct, Geom::OptRect const &b if (needs_opacity) { dc.popGroupToSource(); // pop raw pattern - dc.paint(opacity); // apply opacity + dc.paint(opacity); // apply opacity } cairo_pattern_t *cp = cairo_pattern_create_for_surface(pattern_surface.raw()); // Apply transformation to user space. Also compensate for oversampling. - ink_cairo_pattern_set_matrix(cp, ps2user.inverse() * pattern_surface.drawingTransform() ); + ink_cairo_pattern_set_matrix(cp, ps2user.inverse() * pattern_surface.drawingTransform()); cairo_pattern_set_extend(cp, CAIRO_EXTEND_REPEAT); diff --git a/src/sp-pattern.h b/src/sp-pattern.h index 34dd5a05b..145bb934e 100644 --- a/src/sp-pattern.h +++ b/src/sp-pattern.h @@ -1,9 +1,6 @@ -#ifndef SEEN_SP_PATTERN_H -#define SEEN_SP_PATTERN_H - -/* +/** @file * SVG <pattern> implementation - * + *//* * Author: * Lauris Kaplinski <lauris@kaplinski.com> * Abhishek Sharma @@ -13,95 +10,131 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#define SP_PATTERN(obj) (dynamic_cast<SPPattern*>((SPObject*)obj)) -#define SP_IS_PATTERN(obj) (dynamic_cast<const SPPattern*>((SPObject*)obj) != NULL) +#ifndef SEEN_SP_PATTERN_H +#define SEEN_SP_PATTERN_H -class SPPatternReference; -class SPItem; -typedef struct _GSList GSList; +#include <list> +#include <stddef.h> +#include <glibmm/ustring.h> +#include <sigc++/connection.h> #include "svg/svg-length.h" #include "sp-paint-server.h" #include "uri-references.h" #include "viewbox.h" -#include <sigc++/connection.h> +class SPPatternReference; +class SPItem; +namespace Inkscape { +namespace XML { + +class Node; +} +} + +#define SP_PATTERN(obj) (dynamic_cast<SPPattern *>((SPObject *)obj)) +#define SP_IS_PATTERN(obj) (dynamic_cast<const SPPattern *>((SPObject *)obj) != NULL) class SPPattern : public SPPaintServer, public SPViewBox { public: - SPPattern(); - virtual ~SPPattern(); + enum PatternUnits { UNITS_USERSPACEONUSE, UNITS_OBJECTBOUNDINGBOX }; + + SPPattern(); + virtual ~SPPattern(); /* Reference (href) */ - char *href; + Glib::ustring href; SPPatternReference *ref; - /* patternUnits and patternContentUnits attribute */ - unsigned int patternUnits : 1; - unsigned int patternUnits_set : 1; - unsigned int patternContentUnits : 1; - unsigned int patternContentUnits_set : 1; - /* patternTransform attribute */ - Geom::Affine patternTransform; - unsigned int patternTransform_set : 1; - /* Tile rectangle */ - SVGLength x; - SVGLength y; - SVGLength width; - SVGLength height; - - sigc::connection modified_connection; + gdouble x() const; + gdouble y() const; + gdouble width() const; + gdouble height() const; + Geom::OptRect viewbox() const; + SPPattern::PatternUnits patternUnits() const; + SPPattern::PatternUnits patternContentUnits() const; + Geom::Affine const &getTransform() const; + SPPattern *rootPattern(); // TODO: const + + SPPattern *clone_if_necessary(SPItem *item, const gchar *property); + void transform_multiply(Geom::Affine postmul, bool set); + + /** + * @brief create a new pattern in XML tree + * @return created pattern id + */ + static const gchar *produce(const std::vector<Inkscape::XML::Node *> &reprs, Geom::Rect bounds, + SPDocument *document, Geom::Affine transform, Geom::Affine move); bool isValid() const; - virtual cairo_pattern_t* pattern_new(cairo_t *ct, Geom::OptRect const &bbox, double opacity); + virtual cairo_pattern_t *pattern_new(cairo_t *ct, Geom::OptRect const &bbox, double opacity); protected: - virtual void build(SPDocument* doc, Inkscape::XML::Node* repr); - virtual void release(); - virtual void set(unsigned int key, const gchar* value); - virtual void update(SPCtx* ctx, unsigned int flags); - virtual void modified(unsigned int flags); + virtual void build(SPDocument *doc, Inkscape::XML::Node *repr); + virtual void release(); + virtual void set(unsigned int key, const gchar *value); + virtual void update(SPCtx *ctx, unsigned int flags); + virtual void modified(unsigned int flags); + +private: + bool _hasItemChildren() const; + void _getChildren(std::list<SPObject *> &l); + SPPattern *_chain() const; + + /** + Count how many times pattern is used by the styles of o and its descendants + */ + guint _countHrefs(SPObject *o) const; + + /** + Gets called when the pattern is reattached to another <pattern> + */ + void _onRefChanged(SPObject *old_ref, SPObject *ref); + + /** + Gets called when the referenced <pattern> is changed + */ + void _onRefModified(SPObject *ref, guint flags); + + /* patternUnits and patternContentUnits attribute */ + PatternUnits _pattern_units : 1; + bool _pattern_units_set : 1; + PatternUnits _pattern_content_units : 1; + bool _pattern_content_units_set : 1; + /* patternTransform attribute */ + Geom::Affine _pattern_transform; + bool _pattern_transform_set : 1; + /* Tile rectangle */ + SVGLength _x; + SVGLength _y; + SVGLength _width; + SVGLength _height; + + sigc::connection _modified_connection; }; class SPPatternReference : public Inkscape::URIReference { public: - SPPatternReference (SPObject *obj) : URIReference(obj) {} - SPPattern *getObject() const { + SPPatternReference(SPObject *obj) + : URIReference(obj) + { + } + + SPPattern *getObject() const + { return reinterpret_cast<SPPattern *>(URIReference::getObject()); } protected: - virtual bool _acceptObject(SPObject *obj) const { - return SP_IS_PATTERN (obj); + virtual bool _acceptObject(SPObject *obj) const + { + return SP_IS_PATTERN(obj); } }; -enum { - SP_PATTERN_UNITS_USERSPACEONUSE, - SP_PATTERN_UNITS_OBJECTBOUNDINGBOX -}; - -unsigned int pattern_users (SPPattern *pattern); -SPPattern *pattern_chain (SPPattern *pattern); -SPPattern *sp_pattern_clone_if_necessary (SPItem *item, SPPattern *pattern, const char *property); -void sp_pattern_transform_multiply (SPPattern *pattern, Geom::Affine postmul, bool set); - -const char *pattern_tile (const std::vector<Inkscape::XML::Node*> &reprs, Geom::Rect bounds, SPDocument *document, Geom::Affine transform, Geom::Affine move); - -SPPattern *pattern_getroot (SPPattern *pat); - -unsigned int pattern_patternUnits (SPPattern const *pat); -unsigned int pattern_patternContentUnits (SPPattern const *pat); -Geom::Affine const &pattern_patternTransform(SPPattern const *pat); -double pattern_x (SPPattern const *pat); -double pattern_y (SPPattern const *pat); -double pattern_width (SPPattern const *pat); -double pattern_height (SPPattern const *pat); -Geom::OptRect pattern_viewBox (SPPattern const *pat); - #endif // SEEN_SP_PATTERN_H /* diff --git a/src/sp-use.cpp b/src/sp-use.cpp index 239f487a4..c8a0830c1 100644 --- a/src/sp-use.cpp +++ b/src/sp-use.cpp @@ -22,6 +22,8 @@ #include "display/drawing-group.h" #include "attributes.h" #include "document.h" +#include "sp-clippath.h" +#include "sp-mask.h" #include "sp-factory.h" #include "sp-flowregion.h" #include "uri.h" @@ -426,16 +428,43 @@ void SPUse::move_compensate(Geom::Affine const *mp) { return; Geom::Affine m(*mp); + Geom::Affine t = this->get_parent_transform(); + Geom::Affine clone_move = t.inverse() * m * t; // this is not a simple move, do not try to compensate - if (!(m.isTranslation())) + if (!(m.isTranslation())){ + //BUT move clippaths accordingly. + //if clone has a clippath, move it accordingly + if(clip_ref->getObject()){ + SPObject *clip = clip_ref->getObject()->firstChild() ; + while(clip){ + SPItem *item = (SPItem*) clip; + if(item){ + item->transform *= m; + Geom::Affine identity; + item->doWriteTransform(clip->getRepr(),item->transform, &identity); + } + clip = clip->getNext(); + } + } + if(mask_ref->getObject()){ + SPObject *mask = mask_ref->getObject()->firstChild() ; + while(mask){ + SPItem *item = (SPItem*) mask; + if(item){ + item->transform *= m; + Geom::Affine identity; + item->doWriteTransform(mask->getRepr(),item->transform, &identity); + } + mask = mask->getNext(); + } + } return; + } // restore item->transform field from the repr, in case it was changed by seltrans this->readAttr ("transform"); - Geom::Affine t = this->get_parent_transform(); - Geom::Affine clone_move = t.inverse() * m * t; // calculate the compensation matrix and the advertized movement matrix Geom::Affine advertized_move; @@ -449,6 +478,33 @@ void SPUse::move_compensate(Geom::Affine const *mp) { g_assert_not_reached(); } + //if clone has a clippath, move it accordingly + if(clip_ref->getObject()){ + SPObject *clip = clip_ref->getObject()->firstChild() ; + while(clip){ + SPItem *item = (SPItem*) clip; + if(item){ + item->transform *= clone_move.inverse(); + Geom::Affine identity; + item->doWriteTransform(clip->getRepr(),item->transform, &identity); + } + clip = clip->getNext(); + } + } + if(mask_ref->getObject()){ + SPObject *mask = mask_ref->getObject()->firstChild() ; + while(mask){ + SPItem *item = (SPItem*) mask; + if(item){ + item->transform *= clone_move.inverse(); + Geom::Affine identity; + item->doWriteTransform(mask->getRepr(),item->transform, &identity); + } + mask = mask->getNext(); + } + } + + // commit the compensation this->transform *= clone_move; this->doWriteTransform(this->getRepr(), this->transform, &advertized_move); diff --git a/src/style-enums.h b/src/style-enums.h index f235b6699..29b8e2130 100644 --- a/src/style-enums.h +++ b/src/style-enums.h @@ -74,44 +74,45 @@ enum SPCSSFontStretch { // Can select more than one enum SPCSSFontVariantLigatures { - SP_CSS_FONT_VARIANT_LIGATURES_NORMAL, - SP_CSS_FONT_VARIANT_LIGATURES_NONE, - SP_CSS_FONT_VARIANT_LIGATURES_COMMON, - SP_CSS_FONT_VARIANT_LIGATURES_NO_COMMON, - SP_CSS_FONT_VARIANT_LIGATURES_DISCRETIONARY, - SP_CSS_FONT_VARIANT_LIGATURES_NO_DISCRETIONARY, - SP_CSS_FONT_VARIANT_LIGATURES_HISTORICAL, - SP_CSS_FONT_VARIANT_LIGATURES_NO_HISTORICAL, - SP_CSS_FONT_VARIANT_LIGATURES_CONTEXTUAL, - SP_CSS_FONT_VARIANT_LIGATURES_NO_CONTEXTUAL + SP_CSS_FONT_VARIANT_LIGATURES_NONE = 0, + SP_CSS_FONT_VARIANT_LIGATURES_COMMON = 1, + SP_CSS_FONT_VARIANT_LIGATURES_DISCRETIONARY = 2, + SP_CSS_FONT_VARIANT_LIGATURES_HISTORICAL = 4, + SP_CSS_FONT_VARIANT_LIGATURES_CONTEXTUAL = 8, + SP_CSS_FONT_VARIANT_LIGATURES_NORMAL = 9, // Special case + SP_CSS_FONT_VARIANT_LIGATURES_NOCOMMON = 16, + SP_CSS_FONT_VARIANT_LIGATURES_NODISCRETIONARY = 32, + SP_CSS_FONT_VARIANT_LIGATURES_NOHISTORICAL = 64, + SP_CSS_FONT_VARIANT_LIGATURES_NOCONTEXTUAL = 128 }; enum SPCSSFontVariantPosition { - SP_CSS_FONT_VARIANT_POSITION_NORMAL, - SP_CSS_FONT_VARIANT_POSITION_SUB, - SP_CSS_FONT_VARIANT_POSITION_SUPER + SP_CSS_FONT_VARIANT_POSITION_NORMAL = 1, + SP_CSS_FONT_VARIANT_POSITION_SUB = 2, + SP_CSS_FONT_VARIANT_POSITION_SUPER = 4 }; enum SPCSSFontVariantCaps { - SP_CSS_FONT_VARIANT_CAPS_NORMAL, - SP_CSS_FONT_VARIANT_CAPS_SMALL, - SP_CSS_FONT_VARIANT_CAPS_ALL_SMALL, - SP_CSS_FONT_VARIANT_CAPS_PETITE, - SP_CSS_FONT_VARIANT_CAPS_ALL_PETITE, - SP_CSS_FONT_VARIANT_CAPS_UNICASE, - SP_CSS_FONT_VARIANT_CAPS_TITLING, + SP_CSS_FONT_VARIANT_CAPS_NORMAL = 1, + SP_CSS_FONT_VARIANT_CAPS_SMALL = 2, + SP_CSS_FONT_VARIANT_CAPS_ALL_SMALL = 4, + SP_CSS_FONT_VARIANT_CAPS_PETITE = 8, + SP_CSS_FONT_VARIANT_CAPS_ALL_PETITE = 16, + SP_CSS_FONT_VARIANT_CAPS_UNICASE = 32, + SP_CSS_FONT_VARIANT_CAPS_TITLING = 64 }; +// Can select more than one (see spec) enum SPCSSFontVariantNumeric { - SP_CSS_FONT_VARIANT_NUMERIC_NORMAL, - SP_CSS_FONT_VARIANT_NUMERIC_LINING_NUMS, - SP_CSS_FONT_VARIANT_NUMERIC_OLDSTYLE_NUMS, - SP_CSS_FONT_VARIANT_NUMERIC_PROPORTIONAL_NUMS, - SP_CSS_FONT_VARIANT_NUMERIC_TABULAR_NUMS, - SP_CSS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS, - SP_CSS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS, - SP_CSS_FONT_VARIANT_NUMERIC_ORDINAL, - SP_CSS_FONT_VARIANT_NUMERIC_SLASHED_ZERO + SP_CSS_FONT_VARIANT_NUMERIC_NORMAL = 0, + SP_CSS_FONT_VARIANT_NUMERIC_LINING_NUMS = 1, + SP_CSS_FONT_VARIANT_NUMERIC_OLDSTYLE_NUMS = 2, + SP_CSS_FONT_VARIANT_NUMERIC_PROPORTIONAL_NUMS = 4, + SP_CSS_FONT_VARIANT_NUMERIC_TABULAR_NUMS = 8, + SP_CSS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS = 16, + SP_CSS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS = 32, + SP_CSS_FONT_VARIANT_NUMERIC_ORDINAL = 64, + SP_CSS_FONT_VARIANT_NUMERIC_SLASHED_ZERO = 128 }; enum SPCSSFontVariantAlternates { @@ -376,16 +377,16 @@ static SPStyleEnum const enum_font_stretch[] = { }; static SPStyleEnum const enum_font_variant_ligatures[] = { - {"normal", SP_CSS_FONT_VARIANT_LIGATURES_NORMAL}, - {"none", SP_CSS_FONT_VARIANT_LIGATURES_NONE}, - {"common-ligatures", SP_CSS_FONT_VARIANT_LIGATURES_COMMON}, - {"no-common-ligatures", SP_CSS_FONT_VARIANT_LIGATURES_NO_COMMON}, - {"discretionary-ligatures", SP_CSS_FONT_VARIANT_LIGATURES_DISCRETIONARY}, - {"no-discretionary-ligatures", SP_CSS_FONT_VARIANT_LIGATURES_NO_DISCRETIONARY}, - {"historical-ligatures", SP_CSS_FONT_VARIANT_LIGATURES_HISTORICAL}, - {"nohistorical-ligatures", SP_CSS_FONT_VARIANT_LIGATURES_NO_HISTORICAL}, - {"contextual", SP_CSS_FONT_VARIANT_LIGATURES_CONTEXTUAL}, - {"no-contextual", SP_CSS_FONT_VARIANT_LIGATURES_NO_CONTEXTUAL}, + {"none", SP_CSS_FONT_VARIANT_LIGATURES_NONE}, + {"common-ligatures", SP_CSS_FONT_VARIANT_LIGATURES_COMMON}, + {"discretionary-ligatures", SP_CSS_FONT_VARIANT_LIGATURES_DISCRETIONARY}, + {"historical-ligatures", SP_CSS_FONT_VARIANT_LIGATURES_HISTORICAL}, + {"contextual", SP_CSS_FONT_VARIANT_LIGATURES_CONTEXTUAL}, + {"normal", SP_CSS_FONT_VARIANT_LIGATURES_NORMAL}, + {"no-common-ligatures", SP_CSS_FONT_VARIANT_LIGATURES_NOCOMMON}, + {"no-discretionary-ligatures", SP_CSS_FONT_VARIANT_LIGATURES_NODISCRETIONARY}, + {"no-historical-ligatures", SP_CSS_FONT_VARIANT_LIGATURES_NOHISTORICAL}, + {"no-contextual", SP_CSS_FONT_VARIANT_LIGATURES_NOCONTEXTUAL}, {NULL, -1} }; @@ -401,7 +402,7 @@ static SPStyleEnum const enum_font_variant_caps[] = { {"small-caps", SP_CSS_FONT_VARIANT_CAPS_SMALL}, {"all-small-caps", SP_CSS_FONT_VARIANT_CAPS_ALL_SMALL}, {"petite-caps", SP_CSS_FONT_VARIANT_CAPS_PETITE}, - {"all_petite-caps", SP_CSS_FONT_VARIANT_CAPS_ALL_PETITE}, + {"all-petite-caps", SP_CSS_FONT_VARIANT_CAPS_ALL_PETITE}, {"unicase", SP_CSS_FONT_VARIANT_CAPS_UNICASE}, {"titling", SP_CSS_FONT_VARIANT_CAPS_TITLING}, {NULL, -1} diff --git a/src/style-internal.cpp b/src/style-internal.cpp index 915282301..c117a97f9 100644 --- a/src/style-internal.cpp +++ b/src/style-internal.cpp @@ -45,6 +45,8 @@ #include <sigc++/functors/ptr_fun.h> #include <sigc++/adaptors/bind.h> +#include <glibmm/regex.h> + // TODO REMOVE OR MAKE MEMBER FUNCTIONS void sp_style_fill_paint_server_ref_changed( SPObject *old_ref, SPObject *ref, SPStyle *style); void sp_style_stroke_paint_server_ref_changed(SPObject *old_ref, SPObject *ref, SPStyle *style); @@ -664,6 +666,241 @@ SPIEnum::operator==(const SPIBase& rhs) { } +// SPIEnumBits ---------------------------------------------------------- +// Used for 'font-variant-xxx' +void +SPIEnumBits::read( gchar const *str ) { + + if( !str ) return; + std::cout << "SPIEnumBits: " << name << ": " << str << std::endl; + if( !strcmp(str, "inherit") ) { + set = true; + inherit = true; + } else { + for (unsigned i = 0; enums[i].key; i++) { + if (!strcmp(str, enums[i].key)) { + std::cout << " found: " << enums[i].key << std::endl; + set = true; + inherit = false; + value += enums[i].value; + /* Save copying for values not needing it */ + computed = value; + } + } + } +} + +const Glib::ustring +SPIEnumBits::write( guint const flags, SPIBase const *const base) const { + + SPIEnum const *const my_base = dynamic_cast<const SPIEnum*>(base); + if ( (flags & SP_STYLE_FLAG_ALWAYS) || + ((flags & SP_STYLE_FLAG_IFSET) && this->set) || + ((flags & SP_STYLE_FLAG_IFDIFF) && this->set + && (!my_base->set || this != my_base ))) + { + if (this->inherit) { + return (name + ":inherit;"); + } + if (this->value == 0 ) { + return (name + ":normal"); + } + Glib::ustring return_string = name + ":"; + unsigned j = 1; + for (unsigned i = 0; enums[i].key; ++i) { + if (j & this->value ) { + return_string += enums[i].value + " "; + } + j *= 2; + } + return return_string; + } + return Glib::ustring(""); +} + + +// SPILigatures ----------------------------------------------------- +// Used for 'font-variant-ligatures' +void +SPILigatures::read( gchar const *str ) { + + if( !str ) return; + + value = SP_CSS_FONT_VARIANT_LIGATURES_NORMAL; + if( !strcmp(str, "inherit") ) { + set = true; + inherit = true; + } else if (!strcmp(str, "normal" )) { + // Defaults for TrueType + inherit = false; + set = true; + } else if (!strcmp(str, "none" )) { + value = SP_CSS_FONT_VARIANT_LIGATURES_NONE; + inherit = false; + set = true; + } else { + // We need to parse in order + std::vector<Glib::ustring> tokens = Glib::Regex::split_simple("\\s+", str ); + for( unsigned i = 0; i < tokens.size(); ++i ) { + for (unsigned j = 0; enums[j].key; ++j ) { + if (tokens[i].compare( enums[j].key ) == 0 ) { + set = true; + inherit = false; + if( enums[j].value < SP_CSS_FONT_VARIANT_LIGATURES_NOCOMMON ) { + // Turn on + value |= enums[j].value; + } else { + // Turn off + value &= ~(enums[j].value >> 4); + } + } + } + } + } + computed = value; +} + +const Glib::ustring +SPILigatures::write( guint const flags, SPIBase const *const base) const { + + SPIEnum const *const my_base = dynamic_cast<const SPIEnum*>(base); + if ( (flags & SP_STYLE_FLAG_ALWAYS) || + ((flags & SP_STYLE_FLAG_IFSET) && this->set) || + ((flags & SP_STYLE_FLAG_IFDIFF) && this->set + && (!my_base->set || this != my_base ))) + { + if (this->inherit) { + return (name + ":inherit;"); + } + if (value == SP_CSS_FONT_VARIANT_LIGATURES_NONE ) { + return (name + ":none;"); + } + if (value == SP_CSS_FONT_VARIANT_LIGATURES_NORMAL ) { + return (name + ":normal;"); + } + + Glib::ustring return_string = name + ":"; + if ( !(value & SP_CSS_FONT_VARIANT_LIGATURES_COMMON) ) + return_string += "no-common-ligatures "; + if ( value & SP_CSS_FONT_VARIANT_LIGATURES_DISCRETIONARY ) + return_string += "discretionary-ligatures "; + if ( value & SP_CSS_FONT_VARIANT_LIGATURES_HISTORICAL ) + return_string += "historical-ligatures "; + if ( !(value & SP_CSS_FONT_VARIANT_LIGATURES_CONTEXTUAL) ) + return_string += "no-contextual "; + return_string.erase( return_string.size() - 1 ); + return_string += ";"; + return return_string; + } + return Glib::ustring(""); +} + + +// SPINumeric ----------------------------------------------------- +// Used for 'font-variant-numeric' +void +SPINumeric::read( gchar const *str ) { + + if( !str ) return; + + value = SP_CSS_FONT_VARIANT_NUMERIC_NORMAL; + if( !strcmp(str, "inherit") ) { + set = true; + inherit = true; + } else if (!strcmp(str, "normal" )) { + // Defaults for TrueType + inherit = false; + set = true; + } else { + // We need to parse in order + std::vector<Glib::ustring> tokens = Glib::Regex::split_simple("\\s+", str ); + for( unsigned i = 0; i < tokens.size(); ++i ) { + for (unsigned j = 0; enums[j].key; ++j ) { + if (tokens[i].compare( enums[j].key ) == 0 ) { + set = true; + inherit = false; + value |= enums[j].value; + + // Must switch off incompatible value + switch (enums[j].value ) { + case SP_CSS_FONT_VARIANT_NUMERIC_LINING_NUMS: + value &= ~SP_CSS_FONT_VARIANT_NUMERIC_OLDSTYLE_NUMS; + break; + case SP_CSS_FONT_VARIANT_NUMERIC_OLDSTYLE_NUMS: + value &= ~SP_CSS_FONT_VARIANT_NUMERIC_LINING_NUMS; + break; + + case SP_CSS_FONT_VARIANT_NUMERIC_PROPORTIONAL_NUMS: + value &= ~SP_CSS_FONT_VARIANT_NUMERIC_TABULAR_NUMS; + break; + case SP_CSS_FONT_VARIANT_NUMERIC_TABULAR_NUMS: + value &= ~SP_CSS_FONT_VARIANT_NUMERIC_PROPORTIONAL_NUMS; + break; + + case SP_CSS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS: + value &= ~SP_CSS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS; + break; + case SP_CSS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS: + value &= ~SP_CSS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS; + break; + + case SP_CSS_FONT_VARIANT_NUMERIC_NORMAL: + case SP_CSS_FONT_VARIANT_NUMERIC_ORDINAL: + case SP_CSS_FONT_VARIANT_NUMERIC_SLASHED_ZERO: + // Do nothing + break; + + default: + std::cerr << "SPINumeric::read(): Invalid value." << std::endl; + break; + } + } + } + } + } + computed = value; +} + +const Glib::ustring +SPINumeric::write( guint const flags, SPIBase const *const base) const { + + SPIEnum const *const my_base = dynamic_cast<const SPIEnum*>(base); + if ( (flags & SP_STYLE_FLAG_ALWAYS) || + ((flags & SP_STYLE_FLAG_IFSET) && this->set) || + ((flags & SP_STYLE_FLAG_IFDIFF) && this->set + && (!my_base->set || this != my_base ))) + { + if (this->inherit) { + return (name + ":inherit;"); + } + if (value == SP_CSS_FONT_VARIANT_NUMERIC_NORMAL ) { + return (name + ":normal;"); + } + + Glib::ustring return_string = name + ":"; + if ( value & SP_CSS_FONT_VARIANT_NUMERIC_LINING_NUMS ) + return_string += "lining-nums "; + if ( value & SP_CSS_FONT_VARIANT_NUMERIC_OLDSTYLE_NUMS ) + return_string += "oldstyle-nums "; + if ( value & SP_CSS_FONT_VARIANT_NUMERIC_PROPORTIONAL_NUMS ) + return_string += "proportional-nums "; + if ( value & SP_CSS_FONT_VARIANT_NUMERIC_TABULAR_NUMS ) + return_string += "tabular-nums "; + if ( value & SP_CSS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS ) + return_string += "diagonal-fractions "; + if ( value & SP_CSS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS ) + return_string += "stacked-fractions "; + if ( value & SP_CSS_FONT_VARIANT_NUMERIC_ORDINAL ) + return_string += "ordinal "; + if ( value & SP_CSS_FONT_VARIANT_NUMERIC_SLASHED_ZERO ) + return_string += "slashed-zero "; + return_string.erase( return_string.size() - 1 ); + return_string += ";"; + return return_string; + } + return Glib::ustring(""); +} + // SPIString ------------------------------------------------------------ @@ -1694,6 +1931,11 @@ SPIFontSize::read( gchar const *str ) { unit = length.unit; value = length.value; computed = length.computed; + /* Set a minimum font size to something much smaller than should ever (ever!) be encountered in a real file. + If a bad SVG file is encountered and this is zero odd things + might happen because the inverse is used in some scaling actions. + */ + if ( computed <= 1.0e-32 ) { computed = 1.0e-32; } if( unit == SP_CSS_UNIT_PERCENT ) { type = SP_FONT_SIZE_PERCENTAGE; } else { @@ -1774,6 +2016,11 @@ SPIFontSize::cascade( const SPIBase* const parent ) { break; } } + /* Set a minimum font size to something much smaller than should ever (ever!) be encountered in a real file. + If a bad SVG file is encountered and this is zero odd things + might happen because the inverse is used in some scaling actions. + */ + if ( computed <= 1.0e-32 ) { computed = 1.0e-32; } } else { std::cerr << "SPIFontSize::cascade(): Incorrect parent type" << std::endl; } @@ -1862,6 +2109,11 @@ SPIFontSize::merge( const SPIBase* const parent ) { } } } // Relative size + /* Set a minimum font size to something much smaller than should ever (ever!) be encountered in a real file. + If a bad SVG file is encountered and this is zero odd things + might happen because the inverse is used in some scaling actions. + */ + if ( computed <= 1.0e-32 ) { computed = 1.0e-32; } } // Parent set and not inherit } else { std::cerr << "SPIFontSize::merge(): Incorrect parent type" << std::endl; diff --git a/src/style-internal.h b/src/style-internal.h index a8f0c5096..bd2a92c8c 100644 --- a/src/style-internal.h +++ b/src/style-internal.h @@ -510,6 +510,77 @@ private: }; +/// SPIEnum w/ bits, allows values with multiple key words. +class SPIEnumBits : public SPIEnum +{ + +public: + SPIEnumBits() : + SPIEnum( "anonymous_enumbits", NULL ) + {} + + SPIEnumBits( Glib::ustring const &name, SPStyleEnum const *enums, unsigned value = 0, bool inherits = true ) : + SPIEnum( name, enums, value, inherit ) + {} + + virtual ~SPIEnumBits() + {} + + virtual void read( gchar const *str ); + virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET, + SPIBase const *const base = NULL ) const; + +}; + + +/// SPIEnum w/ extra bits. The 'font-variants-ligatures' property is a complete mess that needs +/// special handling. For OpenType fonts the values 'common-ligatures', 'contextual', +/// 'no-discretionary-ligatures', and 'no-historical-ligatures' are not useful but we still must be +/// able to parse them. +class SPILigatures : public SPIEnum +{ + +public: + SPILigatures() : + SPIEnum( "anonymous_enumligatures", NULL ) + {} + + SPILigatures( Glib::ustring const &name, SPStyleEnum const *enums) : + SPIEnum( name, enums, SP_CSS_FONT_VARIANT_NORMAL ) + {} + + virtual ~SPILigatures() + {} + + virtual void read( gchar const *str ); + virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET, + SPIBase const *const base = NULL ) const; +}; + + +/// SPIEnum w/ extra bits. The 'font-variants-numeric' property is a complete mess that needs +/// special handling. Multiple key words can be specified, some exclusive of others. +class SPINumeric : public SPIEnum +{ + +public: + SPINumeric() : + SPIEnum( "anonymous_enumnumeric", NULL ) + {} + + SPINumeric( Glib::ustring const &name, SPStyleEnum const *enums) : + SPIEnum( name, enums, SP_CSS_FONT_VARIANT_NUMERIC_NORMAL ) + {} + + virtual ~SPINumeric() + {} + + virtual void read( gchar const *str ); + virtual const Glib::ustring write( guint const flags = SP_STYLE_FLAG_IFSET, + SPIBase const *const base = NULL ) const; +}; + + /// String type internal to SPStyle. // Used for 'marker', ..., 'font', 'font-family', 'inkscape-font-specification' class SPIString : public SPIBase diff --git a/src/style-test.h b/src/style-test.h index cd6769b24..c6bb665e0 100644 --- a/src/style-test.h +++ b/src/style-test.h @@ -109,13 +109,13 @@ public: TestCase("font: 12pt/15pt sans-serif", "font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:15pt;font-family:sans-serif"), TestCase("font: 80% sans-serif", - "font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:80.00000119%;line-height:normal;font-family:sans-serif"), + "font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:80%;line-height:normal;font-family:sans-serif"), TestCase("font: x-large/110% 'new century schoolbook', serif", - "font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:x-large;line-height:110.00000238%;font-family:\'new century schoolbook\', serif"), + "font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:x-large;line-height:110%;font-family:\'new century schoolbook\', serif"), TestCase("font: bold italic large Palatino, serif", "font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:large;line-height:normal;font-family:Palatino, serif"), TestCase("font: normal small-caps 120%/120% fantasy", - "font-style:normal;font-variant:small-caps;font-weight:normal;font-stretch:normal;font-size:120.00000477%;line-height:120.00000477%;font-family:fantasy"), + "font-style:normal;font-variant:small-caps;font-weight:normal;font-stretch:normal;font-size:120%;line-height:120%;font-family:fantasy"), TestCase("font: condensed oblique 12pt 'Helvetica Neue', serif;", "font-style:oblique;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:16px;line-height:normal;font-family:\'Helvetica Neue\', serif"), @@ -137,6 +137,34 @@ public: TestCase("font-weight:bolder"), TestCase("font-stretch:condensed"), // SPIEnum + TestCase("font-variant-ligatures:none"), // SPILigatures + TestCase("font-variant-ligatures:normal"), + TestCase("font-variant-ligatures:no-common-ligatures"), + TestCase("font-variant-ligatures:discretionary-ligatures"), + TestCase("font-variant-ligatures:historical-ligatures"), + TestCase("font-variant-ligatures:no-contextual"), + TestCase("font-variant-ligatures:common-ligatures", "font-variant-ligatures:normal"), + TestCase("font-variant-ligatures:contextual", "font-variant-ligatures:normal"), + TestCase("font-variant-ligatures:no-common-ligatures historical-ligatures"), + TestCase("font-variant-ligatures:historical-ligatures no-contextual"), + TestCase("font-variant-position:normal"), + TestCase("font-variant-position:sub"), + TestCase("font-variant-position:super"), + TestCase("font-variant-caps:normal"), + TestCase("font-variant-caps:small-caps"), + TestCase("font-variant-caps:all-small-caps"), + TestCase("font-variant-numeric:normal"), + TestCase("font-variant-numeric:lining-nums"), + TestCase("font-variant-numeric:oldstyle-nums"), + TestCase("font-variant-numeric:proportional-nums"), + TestCase("font-variant-numeric:tabular-nums"), + TestCase("font-variant-numeric:diagonal-fractions"), + TestCase("font-variant-numeric:stacked-fractions"), + TestCase("font-variant-numeric:ordinal"), + TestCase("font-variant-numeric:slashed-zero"), + TestCase("font-variant-numeric:tabular-nums slashed-zero"), + TestCase("font-variant-numeric:tabular-nums proportional-nums", "font-variant-numeric:proportional-nums"), + // Should be moved down TestCase("text-indent:12em"), // SPILength? TestCase("text-align:center"), // SPIEnum diff --git a/src/style.cpp b/src/style.cpp index 49a13604b..b218f4e4d 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -119,10 +119,10 @@ SPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) : font_specification( "-inkscape-font-specification" ), // SPIString // Font variants - font_variant_ligatures( "font-variant-ligatures", enum_font_variant_ligatures, SP_CSS_FONT_VARIANT_LIGATURES_NORMAL ), + font_variant_ligatures( "font-variant-ligatures", enum_font_variant_ligatures ), font_variant_position( "font-variant-position", enum_font_variant_position, SP_CSS_FONT_VARIANT_POSITION_NORMAL ), font_variant_caps( "font-variant-caps", enum_font_variant_caps, SP_CSS_FONT_VARIANT_CAPS_NORMAL ), - font_variant_numeric( "font-variant-numeric", enum_font_variant_numeric, SP_CSS_FONT_VARIANT_NUMERIC_NORMAL ), + font_variant_numeric( "font-variant-numeric", enum_font_variant_numeric ), font_variant_alternates("font-variant-alternates", enum_font_variant_alternates, SP_CSS_FONT_VARIANT_ALTERNATES_NORMAL ), font_variant_east_asian("font-variant-east_asian", enum_font_variant_east_asian, SP_CSS_FONT_VARIANT_EAST_ASIAN_NORMAL ), font_feature_settings( "font-feature-settings", "normal" ), diff --git a/src/style.h b/src/style.h index 2618662f5..8e22b3121 100644 --- a/src/style.h +++ b/src/style.h @@ -113,13 +113,13 @@ public: /* Font variants -------------------- */ /** Font variant ligatures */ - SPIEnum font_variant_ligatures; + SPILigatures font_variant_ligatures; /** Font variant position (subscript/superscript) */ SPIEnum font_variant_position; /** Font variant caps (small caps) */ SPIEnum font_variant_caps; /** Font variant numeric (numerical formatting) */ - SPIEnum font_variant_numeric; + SPINumeric font_variant_numeric; /** Font variant alternates (alternates/swatches) */ SPIEnum font_variant_alternates; /** Font variant East Asian */ diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index 991d11feb..fbf25d039 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -6,6 +6,7 @@ set(ui_SRC interface.cpp object-edit.cpp previewholder.cpp + selected-color.cpp shape-editor.cpp tool-factory.cpp tools-switch.cpp @@ -115,13 +116,20 @@ set(ui_SRC widget/anchor-selector.cpp widget/button.cpp widget/clipmaskicon.cpp + widget/color-entry.cpp + widget/color-icc-selector.cpp + widget/color-notebook.cpp widget/color-picker.cpp widget/color-preview.cpp + widget/color-scales.cpp + widget/color-slider.cpp + widget/color-wheel-selector.cpp widget/dock-item.cpp widget/dock.cpp widget/entity-entry.cpp widget/entry.cpp widget/filter-effect-chooser.cpp + widget/font-variants.cpp widget/frame.cpp widget/gimpcolorwheel.c widget/gimpspinscale.c @@ -174,6 +182,7 @@ set(ui_SRC previewable.h previewfillable.h previewholder.h + selected-color.h shape-editor.h tool-factory.h tools-switch.h @@ -287,14 +296,21 @@ set(ui_SRC widget/anchor-selector.h widget/attr-widget.h widget/button.h + widget/color-entry.h + widget/color-icc-selector.h + widget/color-notebook.h widget/color-picker.h widget/color-preview.h + widget/color-scales.h + widget/color-slider.h + widget/color-wheel-selector.h widget/combo-enums.h widget/dock-item.h widget/dock.h widget/entity-entry.h widget/entry.h widget/filter-effect-chooser.h + widget/font-variants.h widget/frame.h widget/gimpspinscale.h widget/gimpcolorwheel.h diff --git a/src/ui/Makefile_insert b/src/ui/Makefile_insert index f94cba4e9..bbfdb532c 100644 --- a/src/ui/Makefile_insert +++ b/src/ui/Makefile_insert @@ -19,6 +19,8 @@ ink_common_sources += \ ui/previewfillable.h \ ui/previewholder.cpp \ ui/previewholder.h \ + ui/selected-color.h \ + ui/selected-color.cpp \ ui/shape-editor.cpp \ ui/shape-editor.h \ ui/tool-factory.cpp \ diff --git a/src/ui/dialog/layers.cpp b/src/ui/dialog/layers.cpp index 65351cb68..c6888386f 100644 --- a/src/ui/dialog/layers.cpp +++ b/src/ui/dialog/layers.cpp @@ -713,13 +713,21 @@ bool LayersPanel::_handleDragDrop(const Glib::RefPtr<Gdk::DragContext>& /*contex */ void LayersPanel::_doTreeMove( ) { - if (_dnd_source ) { + if (_dnd_source && _dnd_source->getRepr() ) { + if(!_dnd_target){ + _dnd_source->doWriteTransform(_dnd_source->getRepr(), _dnd_source->document->getRoot()->i2doc_affine().inverse() * _dnd_source->i2doc_affine()); + }else{ + SPItem* parent = _dnd_into ? _dnd_target : dynamic_cast<SPItem*>(_dnd_target->parent); + if(parent){ + Geom::Affine move = parent->i2doc_affine().inverse() * _dnd_source->i2doc_affine(); + _dnd_source->doWriteTransform(_dnd_source->getRepr(), move); + } + } _dnd_source->moveTo(_dnd_target, _dnd_into); _selectLayer(_dnd_source); _dnd_source = NULL; DocumentUndo::done( _desktop->doc() , SP_VERB_NONE, _("Moved layer")); - } } diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp index f63b19e86..061055feb 100644 --- a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp +++ b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp @@ -27,7 +27,6 @@ #include "selection-chemistry.h" #include "ui/icon-names.h" #include "ui/widget/imagetoggler.h" -#include "util/units.h" #include <cmath> //#include "event-context.h" @@ -122,18 +121,14 @@ void FilletChamferPropertiesDialog::showDialog( SPDesktop *desktop, Geom::Point knotpoint, const Inkscape::LivePathEffect:: FilletChamferPointArrayParamKnotHolderEntity *pt, - const gchar *unit, bool use_distance, - bool aprox_radius, - Glib::ustring documentUnit) + bool aprox_radius) { FilletChamferPropertiesDialog *dialog = new FilletChamferPropertiesDialog(); dialog->_set_desktop(desktop); - dialog->_set_unit(unit); dialog->_set_use_distance(use_distance); dialog->_set_aprox(aprox_radius); - dialog->_set_document_unit(documentUnit); dialog->_set_knot_point(knotpoint); dialog->_set_pt(pt); @@ -168,7 +163,6 @@ void FilletChamferPropertiesDialog::_apply() } d_pos = _index + (d_pos / 100); } else { - d_pos = Inkscape::Util::Quantity::convert(d_pos, unit, document_unit); d_pos = d_pos * -1; } _knotpoint->knot_set_offset(Geom::Point(d_pos, d_width)); @@ -218,11 +212,9 @@ void FilletChamferPropertiesDialog::_set_knot_point(Geom::Point knotpoint) _fillet_chamfer_position_label.set_label(_("Position (%):")); } else { _flexible = false; - std::string posConcat = Glib::ustring::compose (_("%1 (%2):"), distance_or_radius, unit); + std::string posConcat = Glib::ustring::compose (_("%1:"), distance_or_radius); _fillet_chamfer_position_label.set_label(_(posConcat.c_str())); position = knotpoint[Geom::X] * -1; - - position = Inkscape::Util::Quantity::convert(position, document_unit, unit); } _fillet_chamfer_position_numeric.set_value(position); if (knotpoint.y() == 1) { @@ -247,16 +239,6 @@ void FilletChamferPropertiesDialog::_set_pt( pt); } -void FilletChamferPropertiesDialog::_set_unit(const gchar *abbr) -{ - unit = abbr; -} - -void FilletChamferPropertiesDialog::_set_document_unit(Glib::ustring abbr) -{ - document_unit = abbr; -} - void FilletChamferPropertiesDialog::_set_use_distance(bool use_knot_distance) { use_distance = use_knot_distance; diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.h b/src/ui/dialog/lpe-fillet-chamfer-properties.h index 870a1734f..99494bd63 100644 --- a/src/ui/dialog/lpe-fillet-chamfer-properties.h +++ b/src/ui/dialog/lpe-fillet-chamfer-properties.h @@ -30,10 +30,8 @@ public: static void showDialog(SPDesktop *desktop, Geom::Point knotpoint, const Inkscape::LivePathEffect:: FilletChamferPointArrayParamKnotHolderEntity *pt, - const gchar *unit, bool use_distance, - bool aprox_radius, - Glib::ustring documentUnit); + bool aprox_radius); protected: @@ -68,15 +66,11 @@ protected: void _set_desktop(SPDesktop *desktop); void _set_pt(const Inkscape::LivePathEffect:: FilletChamferPointArrayParamKnotHolderEntity *pt); - void _set_unit(const gchar *abbr); - void _set_document_unit(Glib::ustring abbr); void _set_use_distance(bool use_knot_distance); void _set_aprox(bool aprox_radius); void _apply(); void _close(); bool _flexible; - const gchar *unit; - Glib::ustring document_unit; bool use_distance; bool aprox; void _set_knot_point(Geom::Point knotpoint); diff --git a/src/ui/dialog/object-properties.cpp b/src/ui/dialog/object-properties.cpp index fc21a30d4..75430ed44 100644 --- a/src/ui/dialog/object-properties.cpp +++ b/src/ui/dialog/object-properties.cpp @@ -529,10 +529,12 @@ void ObjectProperties::_imageRenderingChanged() SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_set_property(css, "image-rendering", scale.c_str()); Inkscape::XML::Node *image_node = item->getRepr(); - if( image_node ) { + if (image_node) { sp_repr_css_change(image_node, css, "style"); + DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_ITEM, + _("Set image rendering option")); } - sp_repr_css_attr_unref( css ); + sp_repr_css_attr_unref(css); _blocked = false; } diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp index 781c6ef93..be04e7149 100644 --- a/src/ui/dialog/objects.cpp +++ b/src/ui/dialog/objects.cpp @@ -45,6 +45,7 @@ #include "style.h" #include "ui/tools-switch.h" #include "ui/icon-names.h" +#include "ui/selected-color.h" #include "ui/widget/imagetoggler.h" #include "ui/widget/layertypeicon.h" #include "ui/widget/insertordericon.h" @@ -53,7 +54,7 @@ #include "ui/tools/node-tool.h" #include "ui/tools/tool-base.h" #include "verbs.h" -#include "widgets/sp-color-notebook.h" +#include "ui/widget/color-notebook.h" #include "widgets/icon.h" #include "xml/node.h" #include "xml/node-observer.h" @@ -928,12 +929,12 @@ bool ObjectsPanel::_handleButtonEvent(GdkEventButton* event) //If the current item is not selected, store only it in the highlight source _storeHighlightTarget(iter); } - if (_colorSelector) + if (_selectedColor) { //Set up the color selector SPColor color; color.set( row[_model->_colHighlight] ); - _colorSelector->base->setColorAlpha(color, SP_RGBA32_A_F(row[_model->_colHighlight])); + _selectedColor->setColorAlpha(color, SP_RGBA32_A_F(row[_model->_colHighlight])); } //Show the color selector dialog _colorSelectorDialog.show(); @@ -1440,17 +1441,16 @@ void ObjectsPanel::_setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk: * @param csel Color selector * @param cp Objects panel */ -void sp_highlight_picker_color_mod(SPColorSelector *csel, GObject * cp) +void ObjectsPanel::_highlightPickerColorMod() { SPColor color; float alpha = 0; - csel->base->getColorAlpha(color, alpha); + _selectedColor->colorAlpha(color, alpha); + guint32 rgba = color.toRGBA32( alpha ); - - ObjectsPanel *ptr = reinterpret_cast<ObjectsPanel *>(cp); //Set the highlight color for all items in the _highlight_target (all selected items) - for (std::vector<SPItem *>::iterator iter = ptr->_highlight_target.begin(); iter != ptr->_highlight_target.end(); ++iter) + for (std::vector<SPItem *>::iterator iter = _highlight_target.begin(); iter != _highlight_target.end(); ++iter) { SPItem * target = *iter; target->setHighlightColor(rgba); @@ -1922,18 +1922,16 @@ ObjectsPanel::ObjectsPanel() : _colorSelectorDialog.set_title (_("Select Highlight Color")); _colorSelectorDialog.set_border_width (4); _colorSelectorDialog.property_modal() = true; - _colorSelector = SP_COLOR_SELECTOR(sp_color_selector_new(SP_TYPE_COLOR_NOTEBOOK)); + _selectedColor.reset(new Inkscape::UI::SelectedColor); + Gtk::Widget *color_selector = Gtk::manage(new Inkscape::UI::Widget::ColorNotebook(*_selectedColor)); _colorSelectorDialog.get_vbox()->pack_start ( - *Glib::wrap(&_colorSelector->vbox), true, true, 0); + *color_selector, true, true, 0); - g_signal_connect(G_OBJECT(_colorSelector), "dragged", - G_CALLBACK(sp_highlight_picker_color_mod), (void *)this); - g_signal_connect(G_OBJECT(_colorSelector), "released", - G_CALLBACK(sp_highlight_picker_color_mod), (void *)this); - g_signal_connect(G_OBJECT(_colorSelector), "changed", - G_CALLBACK(sp_highlight_picker_color_mod), (void *)this); + _selectedColor->signal_dragged.connect(sigc::mem_fun(*this, &ObjectsPanel::_highlightPickerColorMod)); + _selectedColor->signal_released.connect(sigc::mem_fun(*this, &ObjectsPanel::_highlightPickerColorMod)); + _selectedColor->signal_changed.connect(sigc::mem_fun(*this, &ObjectsPanel::_highlightPickerColorMod)); - gtk_widget_show(GTK_WIDGET(_colorSelector)); + color_selector->show(); setDesktop( targetDesktop ); @@ -1951,7 +1949,6 @@ ObjectsPanel::~ObjectsPanel() { //Close the highlight selection dialog _colorSelectorDialog.hide(); - _colorSelector = NULL; //Set the desktop to null, which will disconnect all object watchers setDesktop(NULL); diff --git a/src/ui/dialog/objects.h b/src/ui/dialog/objects.h index 1842fea11..7a826d02e 100644 --- a/src/ui/dialog/objects.h +++ b/src/ui/dialog/objects.h @@ -16,6 +16,7 @@ # include <config.h> #endif +#include <boost/scoped_ptr.hpp> #include <gtkmm/box.h> #include <gtkmm/treeview.h> #include <gtkmm/treestore.h> @@ -36,6 +37,9 @@ struct SPColorSelector; namespace Inkscape { namespace UI { + +class SelectedColor; + namespace Dialog { @@ -166,8 +170,7 @@ private: Gtk::Alignment _blur_alignment; Gtk::Dialog _colorSelectorDialog; - SPColorSelector *_colorSelector; - + boost::scoped_ptr<Inkscape::UI::SelectedColor> _selectedColor; //Methods: @@ -233,7 +236,7 @@ private: void setupDialog(const Glib::ustring &title); - friend void sp_highlight_picker_color_mod(SPColorSelector *csel, GObject *cp); + void _highlightPickerColorMod(); }; diff --git a/src/ui/dialog/tags.cpp b/src/ui/dialog/tags.cpp index ed71c826f..f36e3f18d 100644 --- a/src/ui/dialog/tags.cpp +++ b/src/ui/dialog/tags.cpp @@ -51,7 +51,7 @@ #include "ui/tools/tool-base.h" //"event-context.h" #include "selection.h" //#include "dialogs/dialog-events.h" -#include "widgets/sp-color-notebook.h" +#include "ui/widget/color-notebook.h" #include "style.h" #include "filter-chemistry.h" #include "filters/blend.h" diff --git a/src/ui/dialog/text-edit.cpp b/src/ui/dialog/text-edit.cpp index 815aa12ef..1a696c820 100644 --- a/src/ui/dialog/text-edit.cpp +++ b/src/ui/dialog/text-edit.cpp @@ -69,6 +69,7 @@ TextEdit::TextEdit() font_label(_("_Font"), true), layout_frame(), text_label(_("_Text"), true), + vari_label(_("_Variants"), true), setasdefault_button(_("Set as _default")), close_button(Gtk::Stock::CLOSE), apply_button(Gtk::Stock::APPLY), @@ -195,7 +196,8 @@ TextEdit::TextEdit() notebook.append_page(font_vbox, font_label); notebook.append_page(text_vbox, text_label); - + notebook.append_page(vari_vbox, vari_label); + /* Buttons */ setasdefault_button.set_use_underline(true); apply_button.set_can_default(); @@ -216,6 +218,7 @@ TextEdit::TextEdit() setasdefault_button.signal_clicked().connect(sigc::mem_fun(*this, &TextEdit::onSetDefault)); apply_button.signal_clicked().connect(sigc::mem_fun(*this, &TextEdit::onApply)); close_button.signal_clicked().connect(sigc::bind(_signal_response.make_slot(), GTK_RESPONSE_CLOSE)); + fontVariantChangedConn = vari_vbox.connectChanged(sigc::bind(sigc::ptr_fun(&onFontVariantChange), this)); desktopChangeConn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &TextEdit::setTargetDesktop) ); deskTrack.connect(GTK_WIDGET(gobj())); @@ -230,6 +233,7 @@ TextEdit::~TextEdit() selectChangedConn.disconnect(); desktopChangeConn.disconnect(); deskTrack.disconnect(); + fontVariantChangedConn.disconnect(); } void TextEdit::styleButton(Gtk::RadioButton *button, gchar const *tooltip, gchar const *icon_name, Gtk::RadioButton *group_button ) @@ -384,6 +388,11 @@ void TextEdit::onReadSelection ( gboolean dostyle, gboolean /*docontent*/ ) gtk_entry_set_text ((GtkEntry *) gtk_bin_get_child ((GtkBin *) spacing_combo), sstr); g_free(sstr); + // Update font variant widget + //int result_variants = + sp_desktop_query_style (SP_ACTIVE_DESKTOP, &query, QUERY_STYLE_PROPERTY_FONTVARIANTS); + vari_vbox.update( &query ); + } blocked = false; } @@ -510,12 +519,15 @@ SPCSSAttr *TextEdit::fillTextStyle () sp_repr_css_set_property (css, "writing-mode", "tb"); } - // Note that CSS 1.1 does not support line-height; we set it for consistency, but also set + // Note that SVG 1.1 does not support line-height; we set it for consistency, but also set // sodipodi:linespacing for backwards compatibility; in 1.2 we use line-height for flowtext const gchar *sstr = gtk_combo_box_text_get_active_text ((GtkComboBoxText *) spacing_combo); sp_repr_css_set_property (css, "line-height", sstr); + // Font variants + vari_vbox.fill_css( css ); + return css; } @@ -646,6 +658,19 @@ void TextEdit::onFontChange(SPFontSelector * /*fontsel*/, gchar* fontspec, TextE } +void TextEdit::onFontVariantChange(TextEdit *self) +{ + if( self->blocked ) + return; + + SPItem *text = self->getSelectedTextItem (); + + if (text) { + self->apply_button.set_sensitive ( true ); + } + self->setasdefault_button.set_sensitive ( true ); +} + void TextEdit::onStartOffsetChange(GtkTextBuffer * /*text_buffer*/, TextEdit *self) { SPItem *text = self->getSelectedTextItem(); diff --git a/src/ui/dialog/text-edit.h b/src/ui/dialog/text-edit.h index 117ad2e28..41f89b3e7 100644 --- a/src/ui/dialog/text-edit.h +++ b/src/ui/dialog/text-edit.h @@ -32,9 +32,11 @@ #include "ui/widget/panel.h" #include "ui/widget/frame.h" #include "ui/dialog/desktop-tracker.h" +#include "ui/widget/font-variants.h" class SPItem; struct SPFontSelector; +class FontVariants; class font_instance; class SPCSSAttr; @@ -111,6 +113,17 @@ protected: static void onFontChange (SPFontSelector *fontsel, gchar* fontspec, TextEdit *self); /** + * Callback invoked when the user modifies the font variant through the dialog. + * + * onFontChange updates the dialog UI. The subfunction setPreviewText updates the preview label. + * + * @param fontsel pointer to FontVariant (currently not used). + * @param fontspec for the text to be previewed. + * @param self pointer to the current instance of the dialog. + */ + static void onFontVariantChange (TextEdit *self); + + /** * Callback invoked when the user modifies the startOffset of text on a path. * * @param text_buffer pointer to the GtkTextBuffer with the text of the selected text object. @@ -213,6 +226,9 @@ private: GtkWidget *text_view; // TODO - Convert this to a Gtk::TextView, but GtkSpell doesn't seem to work with it GtkTextBuffer *text_buffer; + Inkscape::UI::Widget::FontVariants vari_vbox; + Gtk::Label vari_label; + Gtk::HBox button_row; Gtk::Button setasdefault_button; Gtk::Button close_button; @@ -224,6 +240,7 @@ private: sigc::connection selectChangedConn; sigc::connection subselChangedConn; sigc::connection selectModifiedConn; + sigc::connection fontVariantChangedConn; bool blocked; const Glib::ustring samplephrase; diff --git a/src/ui/selected-color.cpp b/src/ui/selected-color.cpp new file mode 100644 index 000000000..8c37ee7e0 --- /dev/null +++ b/src/ui/selected-color.cpp @@ -0,0 +1,163 @@ +/** @file + * Color selected in color selector widget. + * This file was created during the refactoring of SPColorSelector + *//* + * Authors: + * bulia byak <buliabyak@users.sf.net> + * Jon A. Cruz <jon@joncruz.org> + * Tomasz Boczkowski <penginsbacon@gmail.com> + * + * Copyright (C) 2014 Authors + * Released under GNU GPL, read the file 'COPYING' for more information + */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <glibmm/ustring.h> +#include <cmath> + +#include "svg/svg-icc-color.h" +#include "ui/selected-color.h" + +namespace Inkscape { +namespace UI { + +double const SelectedColor::_EPSILON = 1e-4; + +SelectedColor::SelectedColor() + : _color(0) + , _alpha(1.0) + , _held(false) + , _virgin(true) + , _updating(false) +{ + +} + +SelectedColor::~SelectedColor() { + +} + +void SelectedColor::setColor(SPColor const &color) +{ + setColorAlpha( color, _alpha); +} + +SPColor SelectedColor::color() const +{ + return _color; +} + +void SelectedColor::setAlpha(gfloat alpha) +{ + g_return_if_fail( ( 0.0 <= alpha ) && ( alpha <= 1.0 ) ); + setColorAlpha( _color, alpha); +} + +gfloat SelectedColor::alpha() const +{ + return _alpha; +} + +void SelectedColor::setValue(guint32 value) +{ + SPColor color(value); + gfloat alpha = SP_RGBA32_A_F(value); + setColorAlpha(color, alpha); +} + +guint32 SelectedColor::value() const +{ + return color().toRGBA32(_alpha); +} + +void SelectedColor::setColorAlpha(SPColor const &color, gfloat alpha, bool emit_signal) +{ +#ifdef DUMP_CHANGE_INFO + g_message("SelectedColor::setColorAlpha( this=%p, %f, %f, %f, %s, %f, %s)", this, color.v.c[0], color.v.c[1], color.v.c[2], (color.icc?color.icc->colorProfile.c_str():"<null>"), alpha, (emit_signal?"YES":"no")); +#endif + g_return_if_fail( ( 0.0 <= alpha ) && ( alpha <= 1.0 ) ); + + if (_updating) { + return; + } + +#ifdef DUMP_CHANGE_INFO + g_message("---- SelectedColor::setColorAlpha virgin:%s !close:%s alpha is:%s", + (_virgin?"YES":"no"), + (!color.isClose( _color, _EPSILON )?"YES":"no"), + ((fabs((_alpha) - (alpha)) >= _EPSILON )?"YES":"no") + ); +#endif + + if ( _virgin || !color.isClose( _color, _EPSILON ) || + (fabs((_alpha) - (alpha)) >= _EPSILON )) { + + _virgin = false; + + _color = color; + _alpha = alpha; + + if (emit_signal) + { + _updating = true; + if (_held) { + signal_dragged.emit(); + } else { + signal_changed.emit(); + } + _updating = false; + } + +#ifdef DUMP_CHANGE_INFO + } else { + g_message("++++ SelectedColor::setColorAlpha color:%08x ==> _color:%08X isClose:%s", color.toRGBA32(alpha), _color.toRGBA32(_alpha), + (color.isClose( _color, _EPSILON )?"YES":"no")); +#endif + } +} + +void SelectedColor::colorAlpha(SPColor &color, gfloat &alpha) const { + color = _color; + alpha = _alpha; +} + +void SelectedColor::setHeld(bool held) { + if (_updating) { + return; + } + bool grabbed = held && !_held; + bool released = !held && _held; + + _held = held; + + _updating = true; + if (grabbed) { + signal_grabbed.emit(); + } + + if (released) { + signal_released.emit(); + signal_changed.emit(); + } + _updating = false; +} + +void SelectedColor::preserveICC() { + _color.icc = _color.icc ? new SVGICCColor(*_color.icc) : 0; +} + +} +} + +/* + 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 : diff --git a/src/ui/selected-color.h b/src/ui/selected-color.h new file mode 100644 index 000000000..e9e702d43 --- /dev/null +++ b/src/ui/selected-color.h @@ -0,0 +1,96 @@ +/** @file + * Color selected in color selector widget. + * This file was created during the refactoring of SPColorSelector + *//* + * Authors: + * bulia byak <buliabyak@users.sf.net> + * Jon A. Cruz <jon@joncruz.org> + * Tomasz Boczkowski <penginsbacon@gmail.com> + * + * Copyright (C) 2014 Authors + * Released under GNU GPL, read the file 'COPYING' for more information + */ +#ifndef SEEN_SELECTED_COLOR +#define SEEN_SELECTED_COLOR + +#include <sigc++/signal.h> +#include "color.h" + +namespace Gtk +{ + class Widget; +} + +namespace Inkscape { +namespace UI { + +class SelectedColor { +public: + SelectedColor(); + virtual ~SelectedColor(); + + void setColor(SPColor const &color); + SPColor color() const; + + void setAlpha(gfloat alpha); + gfloat alpha() const; + + void setValue(guint32 value); + guint32 value() const; + + void setColorAlpha(SPColor const &color, gfloat alpha, bool emit_signal = true); + void colorAlpha(SPColor &color, gfloat &alpha) const; + + void setHeld(bool held); + + void preserveICC(); + + sigc::signal<void> signal_grabbed; + sigc::signal<void> signal_dragged; + sigc::signal<void> signal_released; + sigc::signal<void> signal_changed; +private: + // By default, disallow copy constructor and assignment operator + SelectedColor(SelectedColor const &obj); + SelectedColor& operator=(SelectedColor const &obj); + + SPColor _color; + /** + * Color alpha value guaranteed to be in [0, 1]. + */ + gfloat _alpha; + + bool _held; + /** + * This flag is true if no color is set yet + */ + bool _virgin; + + bool _updating; + + static double const _EPSILON; +}; + +class ColorSelectorFactory { +public: + virtual ~ColorSelectorFactory() { + } + + virtual Gtk::Widget* createWidget(SelectedColor &color) const = 0; + virtual Glib::ustring modeName() const = 0; +}; + +} +} + +#endif +/* + 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 : diff --git a/src/ui/widget/Makefile_insert b/src/ui/widget/Makefile_insert index e18b790bd..eb98e6872 100644 --- a/src/ui/widget/Makefile_insert +++ b/src/ui/widget/Makefile_insert @@ -6,10 +6,22 @@ ink_common_sources += \ ui/widget/attr-widget.h \ ui/widget/button.h \ ui/widget/button.cpp \ + ui/widget/color-entry.cpp \ + ui/widget/color-entry.h \ + ui/widget/color-icc-selector.cpp \ + ui/widget/color-icc-selector.h \ + ui/widget/color-notebook.cpp \ + ui/widget/color-notebook.h \ + ui/widget/color-wheel-selector.cpp \ + ui/widget/color-wheel-selector.h \ ui/widget/color-picker.cpp \ ui/widget/color-picker.h \ ui/widget/color-preview.cpp \ ui/widget/color-preview.h \ + ui/widget/color-slider.cpp \ + ui/widget/color-slider.h \ + ui/widget/color-scales.cpp \ + ui/widget/color-scales.h \ ui/widget/combo-enums.h \ ui/widget/dock.h \ ui/widget/dock.cpp \ @@ -21,8 +33,10 @@ ink_common_sources += \ ui/widget/entry.h \ ui/widget/filter-effect-chooser.h \ ui/widget/filter-effect-chooser.cpp \ - ui/widget/gimpspinscale.c \ - ui/widget/gimpspinscale.h \ + ui/widget/font-variants.h \ + ui/widget/font-variants.cpp \ + ui/widget/gimpspinscale.c \ + ui/widget/gimpspinscale.h \ ui/widget/gimpcolorwheel.c \ ui/widget/gimpcolorwheel.h \ ui/widget/frame.cpp \ diff --git a/src/ui/widget/color-entry.cpp b/src/ui/widget/color-entry.cpp new file mode 100644 index 000000000..f5658c3a6 --- /dev/null +++ b/src/ui/widget/color-entry.cpp @@ -0,0 +1,114 @@ +/** @file + * Entry widget for typing color value in css form + *//* + * Authors: + * Tomasz Boczkowski <penginsbacon@gmail.com> + * + * Copyright (C) 2014 Authors + * Released under GNU GPL, read the file 'COPYING' for more information + */ +#include <glibmm.h> +#include <glibmm/i18n.h> +#include <iomanip> + +#include "color-entry.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +ColorEntry::ColorEntry(SelectedColor &color) + : _color(color) + , _updating(false) + , _updatingrgba(false) +{ + _color_changed_connection = color.signal_changed.connect(sigc::mem_fun(this, &ColorEntry::_onColorChanged)); + _color_dragged_connection = color.signal_dragged.connect(sigc::mem_fun(this, &ColorEntry::_onColorChanged)); + _onColorChanged(); + + set_max_length(8); + set_width_chars(8); + set_tooltip_text(_("Hexadecimal RGBA value of the color")); +} + +ColorEntry::~ColorEntry() +{ + _color_changed_connection.disconnect(); + _color_dragged_connection.disconnect(); +} + +void ColorEntry::on_changed() +{ + if (_updating) { + return; + } + if (_updatingrgba) { + return; // Typing text into entry box + } + + Glib::ustring text = get_text(); + bool changed = false; + + // Coerce the value format to eight hex digits + if (!text.empty() && text[0] == '#') { + changed = true; + text.erase(0, 1); + if (text.size() == 6) { + // it was a standard RGB hex + unsigned int alpha = SP_COLOR_F_TO_U(_color.alpha()); + text += Glib::ustring::format(std::hex, std::setw(2), std::setfill(L'0'), alpha); + } + } + + gchar *str = g_strdup(text.c_str()); + gchar *end = 0; + guint64 rgba = g_ascii_strtoull(str, &end, 16); + if (end != str) { + ptrdiff_t len = end - str; + if (len < 8) { + rgba = rgba << (4 * (8 - len)); + } + _updatingrgba = true; + if (changed) { + set_text(str); + } + SPColor color(rgba); + _color.setColorAlpha(color, SP_RGBA32_A_F(rgba)); + _updatingrgba = false; + } + g_free(str); +} + + +void ColorEntry::_onColorChanged() +{ + if (_updatingrgba) { + return; + } + + SPColor color = _color.color(); + gdouble alpha = _color.alpha(); + + guint32 rgba = color.toRGBA32(alpha); + Glib::ustring text = Glib::ustring::format(std::hex, std::setw(8), std::setfill(L'0'), rgba); + + Glib::ustring old_text = get_text(); + if (old_text != text) { + _updating = true; + set_text(text); + _updating = false; + } +} +} +} +} +/* + 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 : diff --git a/src/ui/widget/color-entry.h b/src/ui/widget/color-entry.h new file mode 100644 index 000000000..edabe1980 --- /dev/null +++ b/src/ui/widget/color-entry.h @@ -0,0 +1,54 @@ +/** @file + * Entry widget for typing color value in css form + *//* + * Authors: + * Tomasz Boczkowski <penginsbacon@gmail.com> + * + * Copyright (C) 2014 Authors + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifndef SEEN_COLOR_ENTRY_H +#define SEEN_COLOR_ENTRY_H_ + +#include <gtkmm/entry.h> +#include "ui/selected-color.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +class ColorEntry : public Gtk::Entry +{ +public: + ColorEntry(SelectedColor &color); + virtual ~ColorEntry(); + +protected: + void on_changed(); + +private: + void _onColorChanged(); + + SelectedColor &_color; + sigc::connection _color_changed_connection; + sigc::connection _color_dragged_connection; + bool _updating; + bool _updatingrgba; +}; + +} +} +} + +#endif +/* + 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 : diff --git a/src/ui/widget/color-icc-selector.cpp b/src/ui/widget/color-icc-selector.cpp new file mode 100644 index 000000000..1c31ae33a --- /dev/null +++ b/src/ui/widget/color-icc-selector.cpp @@ -0,0 +1,1079 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <math.h> +#include <gtkmm/adjustment.h> +#include <glibmm/i18n.h> + +#include <gtk/gtk.h> +#include <map> +#include <set> +#include <vector> + +#include "ui/dialog-events.h" +#include "ui/widget/color-icc-selector.h" +#include "ui/widget/color-scales.h" +#include "ui/widget/color-slider.h" +#include "svg/svg-icc-color.h" +#include "colorspace.h" +#include "document.h" +#include "inkscape.h" +#include "profile-manager.h" +#include "widgets/gradient-vector.h" + +#define noDEBUG_LCMS + +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) +#include "color-profile.h" +#include "cms-system.h" +#include "color-profile-cms-fns.h" + +#ifdef DEBUG_LCMS +#include "preferences.h" +#endif // DEBUG_LCMS +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + +#ifdef DEBUG_LCMS +extern guint update_in_progress; +#define DEBUG_MESSAGE(key, ...) \ + { \ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); \ + bool dump = prefs->getBool("/options/scislac/" #key); \ + bool dumpD = prefs->getBool("/options/scislac/" #key "D"); \ + bool dumpD2 = prefs->getBool("/options/scislac/" #key "D2"); \ + dumpD && = ((update_in_progress == 0) || dumpD2); \ + if (dump) { \ + g_message(__VA_ARGS__); \ + } \ + if (dumpD) { \ + GtkWidget *dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, \ + GTK_BUTTONS_OK, __VA_ARGS__); \ + g_signal_connect_swapped(dialog, "response", G_CALLBACK(gtk_widget_destroy), dialog); \ + gtk_widget_show_all(dialog); \ + } \ + } +#endif // DEBUG_LCMS + + +#define XPAD 4 +#define YPAD 1 + +namespace { + +size_t maxColorspaceComponentCount = 0; + +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + +/** + * Internal variable to track all known colorspaces. + */ +std::set<cmsUInt32Number> knownColorspaces; + +#endif + + +/** + * Simple helper to allow bitwise or on GtkAttachOptions. + */ +GtkAttachOptions operator|(GtkAttachOptions lhs, GtkAttachOptions rhs) +{ + return static_cast<GtkAttachOptions>(static_cast<int>(lhs) | static_cast<int>(rhs)); +} + +/** + * Helper function to handle GTK2/GTK3 attachment #ifdef code. + */ +void attachToGridOrTable(GtkWidget *parent, GtkWidget *child, guint left, guint top, guint width, guint height, + bool hexpand = false, bool centered = false, guint xpadding = XPAD, guint ypadding = YPAD) +{ +#if GTK_CHECK_VERSION(3, 0, 0) + #if GTK_CHECK_VERSION(3, 12, 0) + gtk_widget_set_margin_start(child, xpadding); + gtk_widget_set_margin_end(child, xpadding); + #else + gtk_widget_set_margin_left(child, xpadding); + gtk_widget_set_margin_right(child, xpadding); + #endif + + gtk_widget_set_margin_top(child, ypadding); + gtk_widget_set_margin_bottom(child, ypadding); + if (hexpand) { + gtk_widget_set_hexpand(child, TRUE); + } + if (centered) { + gtk_widget_set_halign(child, GTK_ALIGN_CENTER); + gtk_widget_set_valign(child, GTK_ALIGN_CENTER); + } + gtk_grid_attach(GTK_GRID(parent), child, left, top, width, height); +#else + GtkAttachOptions xoptions = + centered ? static_cast<GtkAttachOptions>(0) : hexpand ? (GTK_EXPAND | GTK_FILL) : GTK_FILL; + GtkAttachOptions yoptions = centered ? static_cast<GtkAttachOptions>(0) : GTK_FILL; + + gtk_table_attach(GTK_TABLE(parent), child, left, left + width, top, top + height, xoptions, yoptions, xpadding, + ypadding); +#endif +} + +} // namespace + +/* +icSigRgbData +icSigCmykData +icSigCmyData +*/ +#define SPACE_ID_RGB 0 +#define SPACE_ID_CMY 1 +#define SPACE_ID_CMYK 2 + + +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) +static cmsUInt16Number *getScratch() +{ + // bytes per pixel * input channels * width + static cmsUInt16Number *scritch = static_cast<cmsUInt16Number *>(g_new(cmsUInt16Number, 4 * 1024)); + + return scritch; +} + +colorspace::Component::Component() + : name() + , tip() + , scale(1) +{ +} + +colorspace::Component::Component(std::string const &name, std::string const &tip, guint scale) + : name(name) + , tip(tip) + , scale(scale) +{ +} + +std::vector<colorspace::Component> colorspace::getColorSpaceInfo(uint32_t space) +{ + static std::map<cmsUInt32Number, std::vector<Component> > sets; + if (sets.empty()) { + sets[cmsSigXYZData].push_back(Component("_X", "X", 2)); // TYPE_XYZ_16 + sets[cmsSigXYZData].push_back(Component("_Y", "Y", 1)); + sets[cmsSigXYZData].push_back(Component("_Z", "Z", 2)); + + sets[cmsSigLabData].push_back(Component("_L", "L", 100)); // TYPE_Lab_16 + sets[cmsSigLabData].push_back(Component("_a", "a", 256)); + sets[cmsSigLabData].push_back(Component("_b", "b", 256)); + + // cmsSigLuvData + + sets[cmsSigYCbCrData].push_back(Component("_Y", "Y", 1)); // TYPE_YCbCr_16 + sets[cmsSigYCbCrData].push_back(Component("C_b", "Cb", 1)); + sets[cmsSigYCbCrData].push_back(Component("C_r", "Cr", 1)); + + sets[cmsSigYxyData].push_back(Component("_Y", "Y", 1)); // TYPE_Yxy_16 + sets[cmsSigYxyData].push_back(Component("_x", "x", 1)); + sets[cmsSigYxyData].push_back(Component("y", "y", 1)); + + sets[cmsSigRgbData].push_back(Component(_("_R:"), _("Red"), 1)); // TYPE_RGB_16 + sets[cmsSigRgbData].push_back(Component(_("_G:"), _("Green"), 1)); + sets[cmsSigRgbData].push_back(Component(_("_B:"), _("Blue"), 1)); + + sets[cmsSigGrayData].push_back(Component(_("G:"), _("Gray"), 1)); // TYPE_GRAY_16 + + sets[cmsSigHsvData].push_back(Component(_("_H:"), _("Hue"), 360)); // TYPE_HSV_16 + sets[cmsSigHsvData].push_back(Component(_("_S:"), _("Saturation"), 1)); + sets[cmsSigHsvData].push_back(Component("_V:", "Value", 1)); + + sets[cmsSigHlsData].push_back(Component(_("_H:"), _("Hue"), 360)); // TYPE_HLS_16 + sets[cmsSigHlsData].push_back(Component(_("_L:"), _("Lightness"), 1)); + sets[cmsSigHlsData].push_back(Component(_("_S:"), _("Saturation"), 1)); + + sets[cmsSigCmykData].push_back(Component(_("_C:"), _("Cyan"), 1)); // TYPE_CMYK_16 + sets[cmsSigCmykData].push_back(Component(_("_M:"), _("Magenta"), 1)); + sets[cmsSigCmykData].push_back(Component(_("_Y:"), _("Yellow"), 1)); + sets[cmsSigCmykData].push_back(Component(_("_K:"), _("Black"), 1)); + + sets[cmsSigCmyData].push_back(Component(_("_C:"), _("Cyan"), 1)); // TYPE_CMY_16 + sets[cmsSigCmyData].push_back(Component(_("_M:"), _("Magenta"), 1)); + sets[cmsSigCmyData].push_back(Component(_("_Y:"), _("Yellow"), 1)); + + for (std::map<cmsUInt32Number, std::vector<Component> >::iterator it = sets.begin(); it != sets.end(); ++it) { + knownColorspaces.insert(it->first); + maxColorspaceComponentCount = std::max(maxColorspaceComponentCount, it->second.size()); + } + } + + std::vector<Component> target; + + if (sets.find(space) != sets.end()) { + target = sets[space]; + } + return target; +} + + +std::vector<colorspace::Component> colorspace::getColorSpaceInfo(Inkscape::ColorProfile *prof) +{ + return getColorSpaceInfo(asICColorSpaceSig(prof->getColorSpace())); +} + +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + +namespace Inkscape { +namespace UI { +namespace Widget { + +/** + * Class containing the parts for a single color component's UI presence. + */ +class ComponentUI { + public: + ComponentUI() + : _component() + , _adj(0) + , _slider(0) + , _btn(0) + , _label(0) + , _map(0) + { + } + + ComponentUI(colorspace::Component const &component) + : _component(component) + , _adj(0) + , _slider(0) + , _btn(0) + , _label(0) + , _map(0) + { + } + + colorspace::Component _component; + GtkAdjustment *_adj; // Component adjustment + Inkscape::UI::Widget::ColorSlider *_slider; + GtkWidget *_btn; // spinbutton + GtkWidget *_label; // Label + guchar *_map; +}; + +/** + * Class that implements the internals of the selector. + */ +class ColorICCSelectorImpl { + public: + ColorICCSelectorImpl(ColorICCSelector *owner, SelectedColor &color); + + ~ColorICCSelectorImpl(); + + static void _adjustmentChanged(GtkAdjustment *adjustment, ColorICCSelectorImpl *cs); + + void _sliderGrabbed(); + void _sliderReleased(); + void _sliderChanged(); + + static void _profileSelected(GtkWidget *src, gpointer data); + static void _fixupHit(GtkWidget *src, gpointer data); + +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + void _setProfile(SVGICCColor *profile); + void _switchToProfile(gchar const *name); +#endif + void _updateSliders(gint ignore); + void _profilesChanged(std::string const &name); + + ColorICCSelector *_owner; + SelectedColor &_color; + + gboolean _updating : 1; + gboolean _dragging : 1; + + guint32 _fixupNeeded; + GtkWidget *_fixupBtn; + GtkWidget *_profileSel; + + std::vector<ComponentUI> _compUI; + + GtkAdjustment *_adj; // Channel adjustment + Inkscape::UI::Widget::ColorSlider *_slider; + GtkWidget *_sbtn; // Spinbutton + GtkWidget *_label; // Label + +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + std::string _profileName; + Inkscape::ColorProfile *_prof; + guint _profChannelCount; + gulong _profChangedID; +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) +}; + + + +const gchar *ColorICCSelector::MODE_NAME = N_("CMS"); + +ColorICCSelector::ColorICCSelector(SelectedColor &color) + : _impl(NULL) +{ + _impl = new ColorICCSelectorImpl(this, color); + init(); + color.signal_changed.connect(sigc::mem_fun(this, &ColorICCSelector::_colorChanged)); + // color.signal_dragged.connect(sigc::mem_fun(this, &ColorICCSelector::_colorChanged)); +} + +ColorICCSelector::~ColorICCSelector() +{ + if (_impl) { + delete _impl; + _impl = 0; + } +} + + + +ColorICCSelectorImpl::ColorICCSelectorImpl(ColorICCSelector *owner, SelectedColor &color) + : _owner(owner) + , _color(color) + , _updating(FALSE) + , _dragging(FALSE) + , _fixupNeeded(0) + , _fixupBtn(0) + , _profileSel(0) + , _compUI() + , _adj(0) + , _slider(0) + , _sbtn(0) + , _label(0) +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + , _profileName() + , _prof(0) + , _profChannelCount(0) + , _profChangedID(0) +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) +{ +} + +ColorICCSelectorImpl::~ColorICCSelectorImpl() +{ + _adj = 0; + _sbtn = 0; + _label = 0; +} + +void ColorICCSelector::init() +{ + gint row = 0; + + _impl->_updating = FALSE; + _impl->_dragging = FALSE; + + GtkWidget *t = GTK_WIDGET(gobj()); + + _impl->_compUI.clear(); + + // Create components + row = 0; + + + _impl->_fixupBtn = gtk_button_new_with_label(_("Fix")); + g_signal_connect(G_OBJECT(_impl->_fixupBtn), "clicked", G_CALLBACK(ColorICCSelectorImpl::_fixupHit), + (gpointer)_impl); + gtk_widget_set_sensitive(_impl->_fixupBtn, FALSE); + gtk_widget_set_tooltip_text(_impl->_fixupBtn, _("Fix RGB fallback to match icc-color() value.")); + // gtk_misc_set_alignment( GTK_MISC (_impl->_fixupBtn), 1.0, 0.5 ); + gtk_widget_show(_impl->_fixupBtn); + + attachToGridOrTable(t, _impl->_fixupBtn, 0, row, 1, 1); + + // Combobox and store with 2 columns : label (0) and full name (1) + GtkListStore *store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); + _impl->_profileSel = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)); + + GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(_impl->_profileSel), renderer, TRUE); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(_impl->_profileSel), renderer, "text", 0, NULL); + + GtkTreeIter iter; + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, _("<none>"), 1, _("<none>"), -1); + + gtk_widget_show(_impl->_profileSel); + gtk_combo_box_set_active(GTK_COMBO_BOX(_impl->_profileSel), 0); + + attachToGridOrTable(t, _impl->_profileSel, 1, row, 1, 1); + +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + _impl->_profChangedID = g_signal_connect(G_OBJECT(_impl->_profileSel), "changed", + G_CALLBACK(ColorICCSelectorImpl::_profileSelected), (gpointer)_impl); +#else + gtk_widget_set_sensitive(_impl->_profileSel, false); +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + + + row++; + +// populate the data for colorspaces and channels: +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + std::vector<colorspace::Component> things = colorspace::getColorSpaceInfo(cmsSigRgbData); +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + + for (size_t i = 0; i < maxColorspaceComponentCount; i++) { +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + if (i < things.size()) { + _impl->_compUI.push_back(ComponentUI(things[i])); + } + else { + _impl->_compUI.push_back(ComponentUI()); + } + + std::string labelStr = (i < things.size()) ? things[i].name.c_str() : ""; +#else + _impl->_compUI.push_back(ComponentUI()); + + std::string labelStr = "."; +#endif + + _impl->_compUI[i]._label = gtk_label_new_with_mnemonic(labelStr.c_str()); + gtk_misc_set_alignment(GTK_MISC(_impl->_compUI[i]._label), 1.0, 0.5); + gtk_widget_show(_impl->_compUI[i]._label); + gtk_widget_set_no_show_all(_impl->_compUI[i]._label, TRUE); + + attachToGridOrTable(t, _impl->_compUI[i]._label, 0, row, 1, 1); + + // Adjustment + guint scaleValue = _impl->_compUI[i]._component.scale; + gdouble step = static_cast<gdouble>(scaleValue) / 100.0; + gdouble page = static_cast<gdouble>(scaleValue) / 10.0; + gint digits = (step > 0.9) ? 0 : 2; + _impl->_compUI[i]._adj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, scaleValue, step, page, page)); + + // Slider + _impl->_compUI[i]._slider = + Gtk::manage(new Inkscape::UI::Widget::ColorSlider(Glib::wrap(_impl->_compUI[i]._adj, true))); +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + _impl->_compUI[i]._slider->set_tooltip_text((i < things.size()) ? things[i].tip.c_str() : ""); +#else + _impl->_compUI[i]._slider->set_tooltip_text("."); +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + _impl->_compUI[i]._slider->show(); + _impl->_compUI[i]._slider->set_no_show_all(); + + attachToGridOrTable(t, _impl->_compUI[i]._slider->gobj(), 1, row, 1, 1, true); + + _impl->_compUI[i]._btn = gtk_spin_button_new(_impl->_compUI[i]._adj, step, digits); +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + gtk_widget_set_tooltip_text(_impl->_compUI[i]._btn, (i < things.size()) ? things[i].tip.c_str() : ""); +#else + gtk_widget_set_tooltip_text(_impl->_compUI[i]._btn, "."); +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + sp_dialog_defocus_on_enter(_impl->_compUI[i]._btn); + gtk_label_set_mnemonic_widget(GTK_LABEL(_impl->_compUI[i]._label), _impl->_compUI[i]._btn); + gtk_widget_show(_impl->_compUI[i]._btn); + gtk_widget_set_no_show_all(_impl->_compUI[i]._btn, TRUE); + + attachToGridOrTable(t, _impl->_compUI[i]._btn, 2, row, 1, 1, false, true); + + _impl->_compUI[i]._map = g_new(guchar, 4 * 1024); + memset(_impl->_compUI[i]._map, 0x0ff, 1024 * 4); + + + // Signals + g_signal_connect(G_OBJECT(_impl->_compUI[i]._adj), "value_changed", + G_CALLBACK(ColorICCSelectorImpl::_adjustmentChanged), _impl); + + _impl->_compUI[i]._slider->signal_grabbed.connect(sigc::mem_fun(_impl, &ColorICCSelectorImpl::_sliderGrabbed)); + _impl->_compUI[i]._slider->signal_released.connect( + sigc::mem_fun(_impl, &ColorICCSelectorImpl::_sliderReleased)); + _impl->_compUI[i]._slider->signal_value_changed.connect( + sigc::mem_fun(_impl, &ColorICCSelectorImpl::_sliderChanged)); + + row++; + } + + // Label + _impl->_label = gtk_label_new_with_mnemonic(_("_A:")); + gtk_misc_set_alignment(GTK_MISC(_impl->_label), 1.0, 0.5); + gtk_widget_show(_impl->_label); + + attachToGridOrTable(t, _impl->_label, 0, row, 1, 1); + + // Adjustment + _impl->_adj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 255.0, 1.0, 10.0, 10.0)); + + // Slider + _impl->_slider = Gtk::manage(new Inkscape::UI::Widget::ColorSlider(Glib::wrap(_impl->_adj, true))); + _impl->_slider->set_tooltip_text(_("Alpha (opacity)")); + _impl->_slider->show(); + + attachToGridOrTable(t, _impl->_slider->gobj(), 1, row, 1, 1, true); + + _impl->_slider->setColors(SP_RGBA32_F_COMPOSE(1.0, 1.0, 1.0, 0.0), SP_RGBA32_F_COMPOSE(1.0, 1.0, 1.0, 0.5), + SP_RGBA32_F_COMPOSE(1.0, 1.0, 1.0, 1.0)); + + + // Spinbutton + _impl->_sbtn = gtk_spin_button_new(GTK_ADJUSTMENT(_impl->_adj), 1.0, 0); + gtk_widget_set_tooltip_text(_impl->_sbtn, _("Alpha (opacity)")); + sp_dialog_defocus_on_enter(_impl->_sbtn); + gtk_label_set_mnemonic_widget(GTK_LABEL(_impl->_label), _impl->_sbtn); + gtk_widget_show(_impl->_sbtn); + + attachToGridOrTable(t, _impl->_sbtn, 2, row, 1, 1, false, true); + + // Signals + g_signal_connect(G_OBJECT(_impl->_adj), "value_changed", G_CALLBACK(ColorICCSelectorImpl::_adjustmentChanged), + _impl); + + _impl->_slider->signal_grabbed.connect(sigc::mem_fun(_impl, &ColorICCSelectorImpl::_sliderGrabbed)); + _impl->_slider->signal_released.connect(sigc::mem_fun(_impl, &ColorICCSelectorImpl::_sliderReleased)); + _impl->_slider->signal_value_changed.connect(sigc::mem_fun(_impl, &ColorICCSelectorImpl::_sliderChanged)); + + gtk_widget_show(t); +} + +void ColorICCSelectorImpl::_fixupHit(GtkWidget * /*src*/, gpointer data) +{ + ColorICCSelectorImpl *self = reinterpret_cast<ColorICCSelectorImpl *>(data); + gtk_widget_set_sensitive(self->_fixupBtn, FALSE); + self->_adjustmentChanged(self->_compUI[0]._adj, self); +} + +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) +void ColorICCSelectorImpl::_profileSelected(GtkWidget * /*src*/, gpointer data) +{ + ColorICCSelectorImpl *self = reinterpret_cast<ColorICCSelectorImpl *>(data); + + GtkTreeIter iter; + if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(self->_profileSel), &iter)) { + GtkTreeModel *store = gtk_combo_box_get_model(GTK_COMBO_BOX(self->_profileSel)); + gchar *name = 0; + + gtk_tree_model_get(store, &iter, 1, &name, -1); + self->_switchToProfile(name); + gtk_widget_set_tooltip_text(self->_profileSel, name); + + if (name) { + g_free(name); + } + } +} +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) +void ColorICCSelectorImpl::_switchToProfile(gchar const *name) +{ + bool dirty = false; + SPColor tmp(_color.color()); + + if (name) { + if (tmp.icc && tmp.icc->colorProfile == name) { +#ifdef DEBUG_LCMS + g_message("Already at name [%s]", name); +#endif // DEBUG_LCMS + } + else { +#ifdef DEBUG_LCMS + g_message("Need to switch to profile [%s]", name); +#endif // DEBUG_LCMS + if (tmp.icc) { + tmp.icc->colors.clear(); + } + else { + tmp.icc = new SVGICCColor(); + } + tmp.icc->colorProfile = name; + Inkscape::ColorProfile *newProf = SP_ACTIVE_DOCUMENT->profileManager->find(name); + if (newProf) { + cmsHTRANSFORM trans = newProf->getTransfFromSRGB8(); + if (trans) { + guint32 val = _color.color().toRGBA32(0); + guchar pre[4] = { + static_cast<guchar>(SP_RGBA32_R_U(val)), + static_cast<guchar>(SP_RGBA32_G_U(val)), + static_cast<guchar>(SP_RGBA32_B_U(val)), + 255}; +#ifdef DEBUG_LCMS + g_message("Shoving in [%02x] [%02x] [%02x]", pre[0], pre[1], pre[2]); +#endif // DEBUG_LCMS + cmsUInt16Number post[4] = { 0, 0, 0, 0 }; + cmsDoTransform(trans, pre, post, 1); +#ifdef DEBUG_LCMS + g_message("got on out [%04x] [%04x] [%04x] [%04x]", post[0], post[1], post[2], post[3]); +#endif // DEBUG_LCMS +#if HAVE_LIBLCMS1 + guint count = _cmsChannelsOf(asICColorSpaceSig(newProf->getColorSpace())); +#elif HAVE_LIBLCMS2 + guint count = cmsChannelsOf(asICColorSpaceSig(newProf->getColorSpace())); +#endif + + std::vector<colorspace::Component> things = + colorspace::getColorSpaceInfo(asICColorSpaceSig(newProf->getColorSpace())); + + for (guint i = 0; i < count; i++) { + gdouble val = + (((gdouble)post[i]) / 65535.0) * (gdouble)((i < things.size()) ? things[i].scale : 1); +#ifdef DEBUG_LCMS + g_message(" scaled %d by %d to be %f", i, ((i < things.size()) ? things[i].scale : 1), val); +#endif // DEBUG_LCMS + tmp.icc->colors.push_back(val); + } + cmsHTRANSFORM retrans = newProf->getTransfToSRGB8(); + if (retrans) { + cmsDoTransform(retrans, post, pre, 1); +#ifdef DEBUG_LCMS + g_message(" back out [%02x] [%02x] [%02x]", pre[0], pre[1], pre[2]); +#endif // DEBUG_LCMS + tmp.set(SP_RGBA32_U_COMPOSE(pre[0], pre[1], pre[2], 0xff)); + } + } + } + dirty = true; + } + } + else { +#ifdef DEBUG_LCMS + g_message("NUKE THE ICC"); +#endif // DEBUG_LCMS + if (tmp.icc) { + delete tmp.icc; + tmp.icc = 0; + dirty = true; + _fixupHit(0, this); + } + else { +#ifdef DEBUG_LCMS + g_message("No icc to nuke"); +#endif // DEBUG_LCMS + } + } + + if (dirty) { +#ifdef DEBUG_LCMS + g_message("+----------------"); + g_message("+ new color is [%s]", tmp.toString().c_str()); +#endif // DEBUG_LCMS + _setProfile(tmp.icc); + //_adjustmentChanged( _compUI[0]._adj, SP_COLOR_ICC_SELECTOR(_csel) ); + _color.setColor(tmp); +#ifdef DEBUG_LCMS + g_message("+_________________"); +#endif // DEBUG_LCMS + } +} +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) +void ColorICCSelectorImpl::_profilesChanged(std::string const &name) +{ + GtkComboBox *combo = GTK_COMBO_BOX(_profileSel); + + g_signal_handler_block(G_OBJECT(_profileSel), _profChangedID); + + GtkListStore *store = GTK_LIST_STORE(gtk_combo_box_get_model(combo)); + gtk_list_store_clear(store); + + GtkTreeIter iter; + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, _("<none>"), 1, _("<none>"), -1); + + gtk_combo_box_set_active(combo, 0); + + int index = 1; + const GSList *current = SP_ACTIVE_DOCUMENT->getResourceList("iccprofile"); + while (current) { + SPObject *obj = SP_OBJECT(current->data); + Inkscape::ColorProfile *prof = reinterpret_cast<Inkscape::ColorProfile *>(obj); + + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, gr_ellipsize_text(prof->name, 25).c_str(), 1, prof->name, -1); + + if (name == prof->name) { + gtk_combo_box_set_active(combo, index); + gtk_widget_set_tooltip_text(_profileSel, prof->name); + } + + index++; + current = g_slist_next(current); + } + + g_signal_handler_unblock(G_OBJECT(_profileSel), _profChangedID); +} +#else +void ColorICCSelectorImpl::_profilesChanged(std::string const & /*name*/) {} +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + +void ColorICCSelector::on_show() +{ +#if GTK_CHECK_VERSION(3, 0, 0) + Gtk::Grid::on_show(); +#else + Gtk::Table::on_show(); +#endif + _colorChanged(); +} + +// Helpers for setting color value + +void ColorICCSelector::_colorChanged() +{ + _impl->_updating = TRUE; +// sp_color_icc_set_color( SP_COLOR_ICC( _icc ), &color ); + +#ifdef DEBUG_LCMS + g_message("/^^^^^^^^^ %p::_colorChanged(%08x:%s)", this, _impl->_color.color().toRGBA32(_impl->_color.alpha()), + ((_impl->_color.color().icc) ? _impl->_color.color().icc->colorProfile.c_str() : "<null>")); +#endif // DEBUG_LCMS + +#ifdef DEBUG_LCMS + g_message("FLIPPIES!!!! %p '%s'", _impl->_color.color().icc, + (_impl->_color.color().icc ? _impl->_color.color().icc->colorProfile.c_str() : "<null>")); +#endif // DEBUG_LCMS + + _impl->_profilesChanged((_impl->_color.color().icc) ? _impl->_color.color().icc->colorProfile : std::string("")); + ColorScales::setScaled(_impl->_adj, _impl->_color.alpha()); + +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + _impl->_setProfile(_impl->_color.color().icc); + _impl->_fixupNeeded = 0; + gtk_widget_set_sensitive(_impl->_fixupBtn, FALSE); + + if (_impl->_prof) { + if (_impl->_prof->getTransfToSRGB8()) { + cmsUInt16Number tmp[4]; + for (guint i = 0; i < _impl->_profChannelCount; i++) { + gdouble val = 0.0; + if (_impl->_color.color().icc->colors.size() > i) { + if (_impl->_compUI[i]._component.scale == 256) { + val = (_impl->_color.color().icc->colors[i] + 128.0) / + static_cast<gdouble>(_impl->_compUI[i]._component.scale); + } + else { + val = _impl->_color.color().icc->colors[i] / + static_cast<gdouble>(_impl->_compUI[i]._component.scale); + } + } + tmp[i] = val * 0x0ffff; + } + guchar post[4] = { 0, 0, 0, 0 }; + cmsHTRANSFORM trans = _impl->_prof->getTransfToSRGB8(); + if (trans) { + cmsDoTransform(trans, tmp, post, 1); + guint32 other = SP_RGBA32_U_COMPOSE(post[0], post[1], post[2], 255); + if (other != _impl->_color.color().toRGBA32(255)) { + _impl->_fixupNeeded = other; + gtk_widget_set_sensitive(_impl->_fixupBtn, TRUE); +#ifdef DEBUG_LCMS + g_message("Color needs to change 0x%06x to 0x%06x", _color.toRGBA32(255) >> 8, other >> 8); +#endif // DEBUG_LCMS + } + } + } + } +#else +//(void)color; +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + _impl->_updateSliders(-1); + + + _impl->_updating = FALSE; +#ifdef DEBUG_LCMS + g_message("\\_________ %p::_colorChanged()", this); +#endif // DEBUG_LCMS +} + +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) +void ColorICCSelectorImpl::_setProfile(SVGICCColor *profile) +{ +#ifdef DEBUG_LCMS + g_message("/^^^^^^^^^ %p::_setProfile(%s)", this, ((profile) ? profile->colorProfile.c_str() : "<null>")); +#endif // DEBUG_LCMS + bool profChanged = false; + if (_prof && (!profile || (_profileName != profile->colorProfile))) { + // Need to clear out the prior one + profChanged = true; + _profileName.clear(); + _prof = 0; + _profChannelCount = 0; + } + else if (profile && !_prof) { + profChanged = true; + } + + for (size_t i = 0; i < _compUI.size(); i++) { + gtk_widget_hide(_compUI[i]._label); + _compUI[i]._slider->hide(); + gtk_widget_hide(_compUI[i]._btn); + } + + if (profile) { + _prof = SP_ACTIVE_DOCUMENT->profileManager->find(profile->colorProfile.c_str()); + if (_prof && (asICColorProfileClassSig(_prof->getProfileClass()) != cmsSigNamedColorClass)) { +#if HAVE_LIBLCMS1 + _profChannelCount = _cmsChannelsOf(asICColorSpaceSig(_prof->getColorSpace())); +#elif HAVE_LIBLCMS2 + _profChannelCount = cmsChannelsOf(asICColorSpaceSig(_prof->getColorSpace())); +#endif + + if (profChanged) { + std::vector<colorspace::Component> things = + colorspace::getColorSpaceInfo(asICColorSpaceSig(_prof->getColorSpace())); + for (size_t i = 0; (i < things.size()) && (i < _profChannelCount); ++i) { + _compUI[i]._component = things[i]; + } + + for (guint i = 0; i < _profChannelCount; i++) { + gtk_label_set_text_with_mnemonic(GTK_LABEL(_compUI[i]._label), + (i < things.size()) ? things[i].name.c_str() : ""); + + _compUI[i]._slider->set_tooltip_text((i < things.size()) ? things[i].tip.c_str() : ""); + gtk_widget_set_tooltip_text(_compUI[i]._btn, (i < things.size()) ? things[i].tip.c_str() : ""); + + _compUI[i]._slider->setColors(SPColor(0.0, 0.0, 0.0).toRGBA32(0xff), + SPColor(0.5, 0.5, 0.5).toRGBA32(0xff), + SPColor(1.0, 1.0, 1.0).toRGBA32(0xff)); + /* + _compUI[i]._adj = GTK_ADJUSTMENT( gtk_adjustment_new( val, 0.0, _fooScales[i], + step, page, page ) ); + g_signal_connect( G_OBJECT( _compUI[i]._adj ), "value_changed", G_CALLBACK( + _adjustmentChanged ), _csel ); + + sp_color_slider_set_adjustment( SP_COLOR_SLIDER(_compUI[i]._slider), + _compUI[i]._adj ); + gtk_spin_button_set_adjustment( GTK_SPIN_BUTTON(_compUI[i]._btn), + _compUI[i]._adj ); + gtk_spin_button_set_digits( GTK_SPIN_BUTTON(_compUI[i]._btn), digits ); + */ + gtk_widget_show(_compUI[i]._label); + _compUI[i]._slider->show(); + gtk_widget_show(_compUI[i]._btn); + // gtk_adjustment_set_value( _compUI[i]._adj, 0.0 ); + // gtk_adjustment_set_value( _compUI[i]._adj, val ); + } + for (size_t i = _profChannelCount; i < _compUI.size(); i++) { + gtk_widget_hide(_compUI[i]._label); + _compUI[i]._slider->hide(); + gtk_widget_hide(_compUI[i]._btn); + } + } + } + else { + // Give up for now on named colors + _prof = 0; + } + } + +#ifdef DEBUG_LCMS + g_message("\\_________ %p::_setProfile()", this); +#endif // DEBUG_LCMS +} +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + +void ColorICCSelectorImpl::_updateSliders(gint ignore) +{ +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + if (_color.color().icc) { + for (guint i = 0; i < _profChannelCount; i++) { + gdouble val = 0.0; + if (_color.color().icc->colors.size() > i) { + if (_compUI[i]._component.scale == 256) { + val = (_color.color().icc->colors[i] + 128.0) / static_cast<gdouble>(_compUI[i]._component.scale); + } + else { + val = _color.color().icc->colors[i] / static_cast<gdouble>(_compUI[i]._component.scale); + } + } + gtk_adjustment_set_value(_compUI[i]._adj, val); + } + + if (_prof) { + if (_prof->getTransfToSRGB8()) { + for (guint i = 0; i < _profChannelCount; i++) { + if (static_cast<gint>(i) != ignore) { + cmsUInt16Number *scratch = getScratch(); + cmsUInt16Number filler[4] = { 0, 0, 0, 0 }; + for (guint j = 0; j < _profChannelCount; j++) { + filler[j] = 0x0ffff * ColorScales::getScaled(_compUI[j]._adj); + } + + cmsUInt16Number *p = scratch; + for (guint x = 0; x < 1024; x++) { + for (guint j = 0; j < _profChannelCount; j++) { + if (j == i) { + *p++ = x * 0x0ffff / 1024; + } + else { + *p++ = filler[j]; + } + } + } + + cmsHTRANSFORM trans = _prof->getTransfToSRGB8(); + if (trans) { + cmsDoTransform(trans, scratch, _compUI[i]._map, 1024); + if (_compUI[i]._slider) + { + _compUI[i]._slider->setMap(_compUI[i]._map); + } + } + } + } + } + } + } +#else + (void)ignore; +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + + guint32 start = _color.color().toRGBA32(0x00); + guint32 mid = _color.color().toRGBA32(0x7f); + guint32 end = _color.color().toRGBA32(0xff); + + _slider->setColors(start, mid, end); +} + + +void ColorICCSelectorImpl::_adjustmentChanged(GtkAdjustment *adjustment, ColorICCSelectorImpl *cs) +{ +// // TODO check this. It looks questionable: +// // if a value is entered between 0 and 1 exclusive, normalize it to (int) 0..255 or 0..100 +// if (adjustment->value > 0.0 && adjustment->value < 1.0) { +// gtk_adjustment_set_value( adjustment, floor ((adjustment->value) * adjustment->upper + 0.5) ); +// } + +#ifdef DEBUG_LCMS + g_message("/^^^^^^^^^ %p::_adjustmentChanged()", cs); +#endif // DEBUG_LCMS + + ColorICCSelector *iccSelector = cs->_owner; + if (iccSelector->_impl->_updating) { + return; + } + + iccSelector->_impl->_updating = TRUE; + + gint match = -1; + + SPColor newColor(iccSelector->_impl->_color.color()); + gfloat scaled = ColorScales::getScaled(iccSelector->_impl->_adj); + if (iccSelector->_impl->_adj == adjustment) { +#ifdef DEBUG_LCMS + g_message("ALPHA"); +#endif // DEBUG_LCMS + } + else { +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + for (size_t i = 0; i < iccSelector->_impl->_compUI.size(); i++) { + if (iccSelector->_impl->_compUI[i]._adj == adjustment) { + match = i; + break; + } + } + if (match >= 0) { +#ifdef DEBUG_LCMS + g_message(" channel %d", match); +#endif // DEBUG_LCMS + } + + + cmsUInt16Number tmp[4]; + for (guint i = 0; i < 4; i++) { + tmp[i] = ColorScales::getScaled(iccSelector->_impl->_compUI[i]._adj) * 0x0ffff; + } + guchar post[4] = { 0, 0, 0, 0 }; + + cmsHTRANSFORM trans = iccSelector->_impl->_prof->getTransfToSRGB8(); + if (trans) { + cmsDoTransform(trans, tmp, post, 1); + } + + SPColor other(SP_RGBA32_U_COMPOSE(post[0], post[1], post[2], 255)); + other.icc = new SVGICCColor(); + if (iccSelector->_impl->_color.color().icc) { + other.icc->colorProfile = iccSelector->_impl->_color.color().icc->colorProfile; + } + + guint32 prior = iccSelector->_impl->_color.color().toRGBA32(255); + guint32 newer = other.toRGBA32(255); + + if (prior != newer) { +#ifdef DEBUG_LCMS + g_message("Transformed color from 0x%08x to 0x%08x", prior, newer); + g_message(" ~~~~ FLIP"); +#endif // DEBUG_LCMS + newColor = other; + newColor.icc->colors.clear(); + for (guint i = 0; i < iccSelector->_impl->_profChannelCount; i++) { + gdouble val = ColorScales::getScaled(iccSelector->_impl->_compUI[i]._adj); + val *= iccSelector->_impl->_compUI[i]._component.scale; + if (iccSelector->_impl->_compUI[i]._component.scale == 256) { + val -= 128; + } + newColor.icc->colors.push_back(val); + } + } +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + } + iccSelector->_impl->_color.setColorAlpha(newColor, scaled); + // iccSelector->_updateInternals( newColor, scaled, iccSelector->_impl->_dragging ); + iccSelector->_impl->_updateSliders(match); + + iccSelector->_impl->_updating = FALSE; +#ifdef DEBUG_LCMS + g_message("\\_________ %p::_adjustmentChanged()", cs); +#endif // DEBUG_LCMS +} + +void ColorICCSelectorImpl::_sliderGrabbed() +{ + // ColorICCSelector* iccSelector = dynamic_cast<ColorICCSelector*>(SP_COLOR_SELECTOR(cs)->base); + // if (!iccSelector->_dragging) { + // iccSelector->_dragging = TRUE; + // iccSelector->_grabbed(); + // iccSelector->_updateInternals( iccSelector->_color, ColorScales::getScaled( iccSelector->_impl->_adj ), + // iccSelector->_dragging ); + // } +} + +void ColorICCSelectorImpl::_sliderReleased() +{ + // ColorICCSelector* iccSelector = dynamic_cast<ColorICCSelector*>(SP_COLOR_SELECTOR(cs)->base); + // if (iccSelector->_dragging) { + // iccSelector->_dragging = FALSE; + // iccSelector->_released(); + // iccSelector->_updateInternals( iccSelector->_color, ColorScales::getScaled( iccSelector->_adj ), + // iccSelector->_dragging ); + // } +} + +#ifdef DEBUG_LCMS +void ColorICCSelectorImpl::_sliderChanged(SPColorSlider *slider, SPColorICCSelector *cs) +#else +void ColorICCSelectorImpl::_sliderChanged() +#endif // DEBUG_LCMS +{ +#ifdef DEBUG_LCMS + g_message("Changed %p and %p", slider, cs); +#endif // DEBUG_LCMS + // ColorICCSelector* iccSelector = dynamic_cast<ColorICCSelector*>(SP_COLOR_SELECTOR(cs)->base); + + // iccSelector->_updateInternals( iccSelector->_color, ColorScales::getScaled( iccSelector->_adj ), + // iccSelector->_dragging ); +} + +Gtk::Widget *ColorICCSelectorFactory::createWidget(Inkscape::UI::SelectedColor &color) const +{ + Gtk::Widget *w = Gtk::manage(new ColorICCSelector(color)); + return w; +} + +Glib::ustring ColorICCSelectorFactory::modeName() const { return gettext(ColorICCSelector::MODE_NAME); } +} +} +} +/* + 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 : diff --git a/src/ui/widget/color-icc-selector.h b/src/ui/widget/color-icc-selector.h new file mode 100644 index 000000000..1bcb0a540 --- /dev/null +++ b/src/ui/widget/color-icc-selector.h @@ -0,0 +1,78 @@ +#ifndef SEEN_SP_COLOR_ICC_SELECTOR_H +#define SEEN_SP_COLOR_ICC_SELECTOR_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gtkmm/widget.h> +#if WITH_GTKMM_3_0 +#include <gtkmm/grid.h> +#else +#include <gtkmm/table.h> +#endif + +#include "ui/selected-color.h" + +namespace Inkscape { + +class ColorProfile; + +namespace UI { +namespace Widget { + +class ColorICCSelectorImpl; + +class ColorICCSelector +#if GTK_CHECK_VERSION(3, 0, 0) + : public Gtk::Grid +#else + : public Gtk::Table +#endif + { + public: + static const gchar *MODE_NAME; + + ColorICCSelector(SelectedColor &color); + virtual ~ColorICCSelector(); + + virtual void init(); + + protected: + void on_show(); + + virtual void _colorChanged(); + + void _recalcColor(gboolean changing); + + private: + friend class ColorICCSelectorImpl; + + // By default, disallow copy constructor and assignment operator + ColorICCSelector(const ColorICCSelector &obj); + ColorICCSelector &operator=(const ColorICCSelector &obj); + + ColorICCSelectorImpl *_impl; +}; + + +class ColorICCSelectorFactory : public ColorSelectorFactory { + public: + Gtk::Widget *createWidget(SelectedColor &color) const; + Glib::ustring modeName() const; +}; +} +} +} +#endif // SEEN_SP_COLOR_ICC_SELECTOR_H + +/* + 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 : diff --git a/src/ui/widget/color-notebook.cpp b/src/ui/widget/color-notebook.cpp new file mode 100644 index 000000000..60abf43bf --- /dev/null +++ b/src/ui/widget/color-notebook.cpp @@ -0,0 +1,379 @@ +/** + * @file + * A notebook with RGB, CMYK, CMS, HSL, and Wheel pages - implementation + */ +/* Authors: + * Lauris Kaplinski <lauris@kaplinski.com> + * bulia byak <buliabyak@users.sf.net> + * Tomasz Boczkowski <penginsbacon@gmail.com> (c++-sification) + * + * Copyright (C) 2001-2014 Authors + * + * This code is in public domain + */ + +#undef SPCS_PREVIEW +#define noDUMP_CHANGE_INFO + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "widgets/icon.h" +#include <cstring> +#include <string> +#include <cstdlib> +#include <cstddef> +#include <glibmm/i18n.h> +#include <gtkmm/label.h> +#include <gtkmm/notebook.h> + +#include "preferences.h" +#include "widgets/spw-utilities.h" +#include "svg/svg-icc-color.h" +#include "inkscape.h" +#include "document.h" +#include "profile-manager.h" +#include "color-profile.h" +#include "cms-system.h" +#include "ui/dialog-events.h" +#include "ui/tools-switch.h" +#include "ui/tools/tool-base.h" +#include "ui/widget/color-entry.h" +#include "ui/widget/color-icc-selector.h" +#include "ui/widget/color-notebook.h" +#include "ui/widget/color-scales.h" +#include "ui/widget/color-wheel-selector.h" + +using Inkscape::CMSSystem; + +#define XPAD 4 +#define YPAD 1 + +namespace Inkscape { +namespace UI { +namespace Widget { + + +ColorNotebook::ColorNotebook(SelectedColor &color) +#if GTK_CHECK_VERSION(3, 0, 0) + : Gtk::Grid() +#else + : Gtk::Table(2, 3, false) +#endif + , _selected_color(color) + +{ + Page *page; + + page = new Page(new ColorScalesFactory(SP_COLOR_SCALES_MODE_RGB), true); + _available_pages.push_back(page); + page = new Page(new ColorScalesFactory(SP_COLOR_SCALES_MODE_HSV), true); + _available_pages.push_back(page); + page = new Page(new ColorScalesFactory(SP_COLOR_SCALES_MODE_CMYK), true); + _available_pages.push_back(page); + page = new Page(new ColorWheelSelectorFactory, true); + _available_pages.push_back(page); +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + page = new Page(new ColorICCSelectorFactory, true); + _available_pages.push_back(page); +#endif + + _initUI(); + + _selected_color.signal_changed.connect(sigc::mem_fun(this, &ColorNotebook::_onSelectedColorChanged)); + _selected_color.signal_dragged.connect(sigc::mem_fun(this, &ColorNotebook::_onSelectedColorChanged)); +} + +ColorNotebook::~ColorNotebook() +{ + if (_buttons) { + delete[] _buttons; + _buttons = 0; + } +} + +ColorNotebook::Page::Page(Inkscape::UI::ColorSelectorFactory *selector_factory, bool enabled_full) + : selector_factory(selector_factory) + , enabled_full(enabled_full) +{ +} + + +void ColorNotebook::_initUI() +{ + guint row = 0; + + Gtk::Notebook *notebook = Gtk::manage(new Gtk::Notebook); + notebook->show(); + notebook->set_show_border(false); + notebook->set_show_tabs(false); + _book = GTK_WIDGET(notebook->gobj()); + +#if GTK_CHECK_VERSION(3, 0, 0) + _buttonbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2); + gtk_box_set_homogeneous(GTK_BOX(_buttonbox), TRUE); +#else + _buttonbox = gtk_hbox_new(TRUE, 2); +#endif + + gtk_widget_show(_buttonbox); + _buttons = new GtkWidget *[_available_pages.size()]; + + for (int i = 0; static_cast<size_t>(i) < _available_pages.size(); i++) { + _addPage(_available_pages[i]); + } + + sp_set_font_size_smaller(_buttonbox); + +#if GTK_CHECK_VERSION(3, 0, 0) + #if GTK_CHECK_VERSION(3, 12, 0) + gtk_widget_set_margin_start(_buttonbox, XPAD); + gtk_widget_set_margin_end(_buttonbox, XPAD); + #else + gtk_widget_set_margin_left(_buttonbox, XPAD); + gtk_widget_set_margin_right(_buttonbox, XPAD); + #endif + gtk_widget_set_margin_top(_buttonbox, YPAD); + gtk_widget_set_margin_bottom(_buttonbox, YPAD); + gtk_widget_set_hexpand(_buttonbox, TRUE); + gtk_widget_set_valign(_buttonbox, GTK_ALIGN_CENTER); + attach(*Glib::wrap(_buttonbox), 0, row, 2, 1); +#else + attach(*Glib::wrap(_buttonbox), 0, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, static_cast<Gtk::AttachOptions>(0), + XPAD, YPAD); +#endif + + row++; + +#if GTK_CHECK_VERSION(3, 0, 0) +#if GTK_CHECK_VERSION(3, 12, 0) + gtk_widget_set_margin_start(_book, XPAD * 2); + gtk_widget_set_margin_end(_book, XPAD * 2); +#else + gtk_widget_set_margin_left(_book, XPAD * 2); + gtk_widget_set_margin_right(_book, XPAD * 2); +#endif + gtk_widget_set_margin_top(_book, YPAD); + gtk_widget_set_margin_bottom(_book, YPAD); + gtk_widget_set_hexpand(_book, TRUE); + gtk_widget_set_vexpand(_book, TRUE); + attach(*notebook, 0, row, 2, 1); +#else + attach(*notebook, 0, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::EXPAND | Gtk::FILL, XPAD * 2, YPAD); +#endif + + // restore the last active page + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + _setCurrentPage(prefs->getInt("/colorselector/page", 0)); + row++; + +#if GTK_CHECK_VERSION(3, 0, 0) + GtkWidget *rgbabox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); +#else + GtkWidget *rgbabox = gtk_hbox_new(FALSE, 0); +#endif + +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + /* Create color management icons */ + _box_colormanaged = gtk_event_box_new(); + GtkWidget *colormanaged = gtk_image_new_from_icon_name("color-management-icon", GTK_ICON_SIZE_SMALL_TOOLBAR); + gtk_container_add(GTK_CONTAINER(_box_colormanaged), colormanaged); + gtk_widget_set_tooltip_text(_box_colormanaged, _("Color Managed")); + gtk_widget_set_sensitive(_box_colormanaged, false); + gtk_box_pack_start(GTK_BOX(rgbabox), _box_colormanaged, FALSE, FALSE, 2); + + _box_outofgamut = gtk_event_box_new(); + GtkWidget *outofgamut = gtk_image_new_from_icon_name("out-of-gamut-icon", GTK_ICON_SIZE_SMALL_TOOLBAR); + gtk_container_add(GTK_CONTAINER(_box_outofgamut), outofgamut); + gtk_widget_set_tooltip_text(_box_outofgamut, _("Out of gamut!")); + gtk_widget_set_sensitive(_box_outofgamut, false); + gtk_box_pack_start(GTK_BOX(rgbabox), _box_outofgamut, FALSE, FALSE, 2); + + _box_toomuchink = gtk_event_box_new(); + GtkWidget *toomuchink = gtk_image_new_from_icon_name("too-much-ink-icon", GTK_ICON_SIZE_SMALL_TOOLBAR); + gtk_container_add(GTK_CONTAINER(_box_toomuchink), toomuchink); + gtk_widget_set_tooltip_text(_box_toomuchink, _("Too much ink!")); + gtk_widget_set_sensitive(_box_toomuchink, false); + gtk_box_pack_start(GTK_BOX(rgbabox), _box_toomuchink, FALSE, FALSE, 2); +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + + + /* Color picker */ + GtkWidget *picker = gtk_image_new_from_icon_name("color-picker", GTK_ICON_SIZE_SMALL_TOOLBAR); + _btn_picker = gtk_button_new(); + gtk_button_set_relief(GTK_BUTTON(_btn_picker), GTK_RELIEF_NONE); + gtk_container_add(GTK_CONTAINER(_btn_picker), picker); + gtk_widget_set_tooltip_text(_btn_picker, _("Pick colors from image")); + gtk_box_pack_start(GTK_BOX(rgbabox), _btn_picker, FALSE, FALSE, 2); + g_signal_connect(G_OBJECT(_btn_picker), "clicked", G_CALLBACK(ColorNotebook::_onPickerClicked), this); + + /* Create RGBA entry and color preview */ + _rgbal = gtk_label_new_with_mnemonic(_("RGBA_:")); + gtk_misc_set_alignment(GTK_MISC(_rgbal), 1.0, 0.5); + gtk_box_pack_start(GTK_BOX(rgbabox), _rgbal, TRUE, TRUE, 2); + + ColorEntry *rgba_entry = Gtk::manage(new ColorEntry(_selected_color)); + sp_dialog_defocus_on_enter(GTK_WIDGET(rgba_entry->gobj())); + gtk_box_pack_start(GTK_BOX(rgbabox), GTK_WIDGET(rgba_entry->gobj()), FALSE, FALSE, 0); + gtk_label_set_mnemonic_widget(GTK_LABEL(_rgbal), GTK_WIDGET(rgba_entry->gobj())); + + sp_set_font_size_smaller(rgbabox); + gtk_widget_show_all(rgbabox); + +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + // the "too much ink" icon is initially hidden + gtk_widget_hide(GTK_WIDGET(_box_toomuchink)); +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + +#if GTK_CHECK_VERSION(3, 0, 0) + #if GTK_CHECK_VERSION(3, 12, 0) + gtk_widget_set_margin_start(rgbabox, XPAD); + gtk_widget_set_margin_end(rgbabox, XPAD); + #else + gtk_widget_set_margin_left(rgbabox, XPAD); + gtk_widget_set_margin_right(rgbabox, XPAD); + #endif + gtk_widget_set_margin_top(rgbabox, YPAD); + gtk_widget_set_margin_bottom(rgbabox, YPAD); + attach(*Glib::wrap(rgbabox), 0, row, 2, 1); +#else + attach(*Glib::wrap(rgbabox), 0, 2, row, row + 1, Gtk::FILL, Gtk::SHRINK, XPAD, YPAD); +#endif + +#ifdef SPCS_PREVIEW + _p = sp_color_preview_new(0xffffffff); + gtk_widget_show(_p); + attach(*Glib::wrap(_p), 2, 3, row, row + 1, Gtk::FILL, Gtk::FILL, XPAD, YPAD); +#endif + + g_signal_connect(G_OBJECT(_book), "switch-page", G_CALLBACK(ColorNotebook::_onPageSwitched), this); +} + +void ColorNotebook::_onPickerClicked(GtkWidget * /*widget*/, ColorNotebook * /*colorbook*/) +{ + // Set the dropper into a "one click" mode, so it reverts to the previous tool after a click + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setBool("/tools/dropper/onetimepick", true); + Inkscape::UI::Tools::sp_toggle_dropper(SP_ACTIVE_DESKTOP); +} + +void ColorNotebook::_onButtonClicked(GtkWidget *widget, ColorNotebook *nb) +{ + if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { + return; + } + + for (gint i = 0; i < gtk_notebook_get_n_pages(GTK_NOTEBOOK(nb->_book)); i++) { + if (nb->_buttons[i] == widget) { + gtk_notebook_set_current_page(GTK_NOTEBOOK(nb->_book), i); + } + } +} + +void ColorNotebook::_onSelectedColorChanged() { _updateICCButtons(); } + +void ColorNotebook::_onPageSwitched(GtkNotebook *notebook, GtkWidget *page, guint page_num, ColorNotebook *colorbook) +{ + if (colorbook->get_visible()) { + // remember the page we switched to + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setInt("/colorselector/page", page_num); + } +} + + +// TODO pass in param so as to avoid the need for SP_ACTIVE_DOCUMENT +void ColorNotebook::_updateICCButtons() +{ + SPColor color = _selected_color.color(); + gfloat alpha = _selected_color.alpha(); + + g_return_if_fail((0.0 <= alpha) && (alpha <= 1.0)); + +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + /* update color management icon*/ + gtk_widget_set_sensitive(_box_colormanaged, color.icc != NULL); + + /* update out-of-gamut icon */ + gtk_widget_set_sensitive(_box_outofgamut, false); + if (color.icc) { + Inkscape::ColorProfile *target_profile = + SP_ACTIVE_DOCUMENT->profileManager->find(color.icc->colorProfile.c_str()); + if (target_profile) + gtk_widget_set_sensitive(_box_outofgamut, target_profile->GamutCheck(color)); + } + + /* update too-much-ink icon */ + gtk_widget_set_sensitive(_box_toomuchink, false); + if (color.icc) { + Inkscape::ColorProfile *prof = SP_ACTIVE_DOCUMENT->profileManager->find(color.icc->colorProfile.c_str()); + if (prof && CMSSystem::isPrintColorSpace(prof)) { + gtk_widget_show(GTK_WIDGET(_box_toomuchink)); + double ink_sum = 0; + for (unsigned int i = 0; i < color.icc->colors.size(); i++) { + ink_sum += color.icc->colors[i]; + } + + /* Some literature states that when the sum of paint values exceed 320%, it is considered to be a satured + color, + which means the paper can get too wet due to an excessive ammount of ink. This may lead to several + issues + such as misalignment and poor quality of printing in general.*/ + if (ink_sum > 3.2) + gtk_widget_set_sensitive(_box_toomuchink, true); + } + else { + gtk_widget_hide(GTK_WIDGET(_box_toomuchink)); + } + } +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) +} + +void ColorNotebook::_setCurrentPage(int i) +{ + gtk_notebook_set_current_page(GTK_NOTEBOOK(_book), i); + + if (_buttons && (static_cast<size_t>(i) < _available_pages.size())) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(_buttons[i]), TRUE); + } +} + +void ColorNotebook::_addPage(Page &page) +{ + Gtk::Widget *selector_widget; + + selector_widget = page.selector_factory->createWidget(_selected_color); + if (selector_widget) { + selector_widget->show(); + + Glib::ustring mode_name = page.selector_factory->modeName(); + Gtk::Widget *tab_label = Gtk::manage(new Gtk::Label(mode_name)); + gint page_num = gtk_notebook_append_page(GTK_NOTEBOOK(_book), selector_widget->gobj(), tab_label->gobj()); + + _buttons[page_num] = gtk_radio_button_new_with_label(NULL, mode_name.c_str()); + gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(_buttons[page_num]), FALSE); + if (page_num > 0) { + GSList *group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(_buttons[0])); + gtk_radio_button_set_group(GTK_RADIO_BUTTON(_buttons[page_num]), group); + } + gtk_widget_show(_buttons[page_num]); + gtk_box_pack_start(GTK_BOX(_buttonbox), _buttons[page_num], TRUE, TRUE, 0); + + g_signal_connect(G_OBJECT(_buttons[page_num]), "clicked", G_CALLBACK(_onButtonClicked), this); + } +} +} +} +} + +/* + 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 : diff --git a/src/ui/widget/color-notebook.h b/src/ui/widget/color-notebook.h new file mode 100644 index 000000000..d28028c72 --- /dev/null +++ b/src/ui/widget/color-notebook.h @@ -0,0 +1,99 @@ +/** + * @file + * A notebook with RGB, CMYK, CMS, HSL, and Wheel pages + */ +/* Authors: + * Lauris Kaplinski <lauris@kaplinski.com> + * bulia byak <buliabyak@users.sf.net> + * Tomasz Boczkowski <penginsbacon@gmail.com> (c++-sification) + * + * Copyright (C) 2001-2014 Authors + * + * This code is in public domain + */ +#ifndef SEEN_SP_COLOR_NOTEBOOK_H +#define SEEN_SP_COLOR_NOTEBOOK_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <boost/ptr_container/ptr_vector.hpp> +#if WITH_GTKMM_3_0 +#include <gtkmm/grid.h> +#else +#include <gtkmm/table.h> +#endif +#include <gtk/gtk.h> +#include <glib.h> + +#include "color.h" +#include "ui/selected-color.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +class ColorNotebook +#if GTK_CHECK_VERSION(3, 0, 0) + : public Gtk::Grid +#else + : public Gtk::Table +#endif +{ +public: + ColorNotebook(SelectedColor &color); + virtual ~ColorNotebook(); + +protected: + struct Page { + Page(Inkscape::UI::ColorSelectorFactory *selector_factory, bool enabled_full); + + Inkscape::UI::ColorSelectorFactory *selector_factory; + bool enabled_full; + }; + + virtual void _initUI(); + void _addPage(Page &page); + + static void _onButtonClicked(GtkWidget *widget, ColorNotebook *colorbook); + static void _onPickerClicked(GtkWidget *widget, ColorNotebook *colorbook); + static void _onPageSwitched(GtkNotebook *notebook, GtkWidget *page, guint page_num, ColorNotebook *colorbook); + virtual void _onSelectedColorChanged(); + + void _updateICCButtons(); + void _setCurrentPage(int i); + + Inkscape::UI::SelectedColor &_selected_color; + gulong _entryId; + GtkWidget *_book; + GtkWidget *_buttonbox; + GtkWidget **_buttons; + GtkWidget *_rgbal; /* RGBA entry */ +#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + GtkWidget *_box_outofgamut, *_box_colormanaged, *_box_toomuchink; +#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) + GtkWidget *_btn_picker; + GtkWidget *_p; /* Color preview */ + boost::ptr_vector<Page> _available_pages; + +private: + // By default, disallow copy constructor and assignment operator + ColorNotebook(const ColorNotebook &obj); + ColorNotebook &operator=(const ColorNotebook &obj); +}; +} +} +} +#endif // SEEN_SP_COLOR_NOTEBOOK_H +/* + 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 : + diff --git a/src/ui/widget/color-picker.cpp b/src/ui/widget/color-picker.cpp index d4c4d394e..a66fbfc9c 100644 --- a/src/ui/widget/color-picker.cpp +++ b/src/ui/widget/color-picker.cpp @@ -17,7 +17,7 @@ #include "document-undo.h" #include "ui/dialog-events.h" -#include "widgets/sp-color-notebook.h" +#include "ui/widget/color-notebook.h" #include "verbs.h" @@ -27,8 +27,6 @@ namespace Inkscape { namespace UI { namespace Widget { -void sp_color_picker_color_mod(SPColorSelector *csel, GObject *cp); - ColorPicker::ColorPicker (const Glib::ustring& title, const Glib::ustring& tip, guint32 rgba, bool undo) : _preview(rgba), _title(title), _rgba(rgba), _undo(undo), @@ -39,12 +37,15 @@ ColorPicker::ColorPicker (const Glib::ustring& title, const Glib::ustring& tip, _preview.show(); add (_preview); set_tooltip_text (tip); + + _selected_color.signal_changed.connect(sigc::mem_fun(this, &ColorPicker::_onSelectedColorChanged)); + _selected_color.signal_dragged.connect(sigc::mem_fun(this, &ColorPicker::_onSelectedColorChanged)); + _selected_color.signal_released.connect(sigc::mem_fun(this, &ColorPicker::_onSelectedColorChanged)); } ColorPicker::~ColorPicker() { closeWindow(); - _colorSelector = NULL; } void ColorPicker::setupDialog(const Glib::ustring &title) @@ -55,25 +56,17 @@ void ColorPicker::setupDialog(const Glib::ustring &title) _colorSelectorDialog.hide(); _colorSelectorDialog.set_title (title); _colorSelectorDialog.set_border_width (4); - _colorSelector = SP_COLOR_SELECTOR(sp_color_selector_new(SP_TYPE_COLOR_NOTEBOOK)); + + _color_selector = Gtk::manage(new ColorNotebook(_selected_color)); #if WITH_GTKMM_3_0 _colorSelectorDialog.get_content_area()->pack_start ( - *Glib::wrap(&_colorSelector->vbox), true, true, 0); + *_color_selector, true, true, 0); #else _colorSelectorDialog.get_vbox()->pack_start ( - *Glib::wrap(&_colorSelector->vbox), true, true, 0); + *_color_selector, true, true, 0); #endif - - g_signal_connect(G_OBJECT(_colorSelector), "dragged", - G_CALLBACK(sp_color_picker_color_mod), (void *)this); - g_signal_connect(G_OBJECT(_colorSelector), "released", - G_CALLBACK(sp_color_picker_color_mod), (void *)this); - g_signal_connect(G_OBJECT(_colorSelector), "changed", - G_CALLBACK(sp_color_picker_color_mod), (void *)this); - - gtk_widget_show(GTK_WIDGET(_colorSelector)); - + _color_selector->show(); } void ColorPicker::setRgba32 (guint32 rgba) @@ -82,11 +75,11 @@ void ColorPicker::setRgba32 (guint32 rgba) _preview.setRgba32 (rgba); _rgba = rgba; - if (_colorSelector) + if (_color_selector) { - SPColor color; - color.set( rgba ); - _colorSelector->base->setColorAlpha(color, SP_RGBA32_A_F(rgba)); + _updating = true; + _selected_color.setValue(rgba); + _updating = false; } } @@ -97,11 +90,11 @@ void ColorPicker::closeWindow() void ColorPicker::on_clicked() { - if (_colorSelector) + if (_color_selector) { - SPColor color; - color.set( _rgba ); - _colorSelector->base->setColorAlpha(color, SP_RGBA32_A_F(_rgba)); + _updating = true; + _selected_color.setValue(_rgba); + _updating = false; } _colorSelectorDialog.show(); } @@ -110,34 +103,31 @@ void ColorPicker::on_changed (guint32) { } -void sp_color_picker_color_mod(SPColorSelector *csel, GObject *cp) -{ +void ColorPicker::_onSelectedColorChanged() { + if (_updating) { + return; + } + if (_in_use) { return; } else { _in_use = true; } - SPColor color; - float alpha = 0; - csel->base->getColorAlpha(color, alpha); - guint32 rgba = color.toRGBA32( alpha ); - - ColorPicker *ptr = reinterpret_cast<ColorPicker *>(cp); - - (ptr->_preview).setRgba32 (rgba); + guint32 rgba = _selected_color.value(); + _preview.setRgba32(rgba); - if (ptr->_undo && SP_ACTIVE_DESKTOP) + if (_undo && SP_ACTIVE_DESKTOP) { DocumentUndo::done(SP_ACTIVE_DESKTOP->getDocument(), SP_VERB_NONE, /* TODO: annotate */ "color-picker.cpp:130"); + } - ptr->on_changed (rgba); + on_changed(rgba); _in_use = false; - ptr->_changed_signal.emit (rgba); - ptr->_rgba = rgba; + _changed_signal.emit(rgba); + _rgba = rgba; } - }//namespace Widget }//namespace UI }//namespace Inkscape diff --git a/src/ui/widget/color-picker.h b/src/ui/widget/color-picker.h index 99904b081..e8a738b5b 100644 --- a/src/ui/widget/color-picker.h +++ b/src/ui/widget/color-picker.h @@ -18,6 +18,7 @@ #include <gtkmm/dialog.h> #include <gtkmm/button.h> #include <sigc++/sigc++.h> +#include "ui/selected-color.h" #include "ui/widget/color-preview.h" struct SPColorSelector; @@ -49,7 +50,7 @@ public: protected: - friend void sp_color_picker_color_mod(SPColorSelector *csel, GObject *cp); + void _onSelectedColorChanged(); virtual void on_clicked(); virtual void on_changed (guint32); @@ -59,13 +60,14 @@ protected: sigc::signal<void,guint32> _changed_signal; guint32 _rgba; bool _undo; - + bool _updating; //Dialog void setupDialog(const Glib::ustring &title); //Inkscape::UI::Dialog::Dialog _colorSelectorDialog; Gtk::Dialog _colorSelectorDialog; - SPColorSelector *_colorSelector; + SelectedColor _selected_color; + Gtk::Widget *_color_selector; }; }//namespace Widget diff --git a/src/ui/widget/color-scales.cpp b/src/ui/widget/color-scales.cpp new file mode 100644 index 000000000..170f83887 --- /dev/null +++ b/src/ui/widget/color-scales.cpp @@ -0,0 +1,677 @@ +/* + * bulia byak <buliabyak@users.sf.net> + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <math.h> +#include <gtkmm/adjustment.h> +#include <glibmm/i18n.h> +#include <gtk/gtk.h> + +#include "svg/svg-icc-color.h" +#include "ui/dialog-events.h" +#include "ui/widget/color-scales.h" +#include "ui/widget/color-slider.h" + +#define CSC_CHANNEL_R (1 << 0) +#define CSC_CHANNEL_G (1 << 1) +#define CSC_CHANNEL_B (1 << 2) +#define CSC_CHANNEL_A (1 << 3) +#define CSC_CHANNEL_H (1 << 0) +#define CSC_CHANNEL_S (1 << 1) +#define CSC_CHANNEL_V (1 << 2) +#define CSC_CHANNEL_C (1 << 0) +#define CSC_CHANNEL_M (1 << 1) +#define CSC_CHANNEL_Y (1 << 2) +#define CSC_CHANNEL_K (1 << 3) +#define CSC_CHANNEL_CMYKA (1 << 4) + +#define CSC_CHANNELS_ALL 0 + +#define XPAD 4 +#define YPAD 1 + +#define noDUMP_CHANGE_INFO 1 + +namespace Inkscape { +namespace UI { +namespace Widget { + + +static const gchar *sp_color_scales_hue_map(); + +const gchar *ColorScales::SUBMODE_NAMES[] = { N_("None"), N_("RGB"), N_("HSL"), N_("CMYK") }; + +ColorScales::ColorScales(SelectedColor &color, SPColorScalesMode mode) +#if GTK_CHECK_VERSION(3, 0, 0) + : Gtk::Grid() +#else + : Gtk::Table(5, 3, false) +#endif + , _color(color) + , _rangeLimit(255.0) + , _updating(FALSE) + , _dragging(FALSE) +{ + for (gint i = 0; i < 5; i++) { + _l[i] = 0; + _a[i] = 0; + _s[i] = 0; + _b[i] = 0; + } + + _initUI(mode); + + _color.signal_changed.connect(sigc::mem_fun(this, &ColorScales::_onColorChanged)); + _color.signal_dragged.connect(sigc::mem_fun(this, &ColorScales::_onColorChanged)); +} + +ColorScales::~ColorScales() +{ + for (gint i = 0; i < 5; i++) { + _l[i] = 0; + _a[i] = 0; + _s[i] = 0; + _b[i] = 0; + } +} + +void ColorScales::_initUI(SPColorScalesMode mode) +{ + gint i; + + _updating = FALSE; + _dragging = FALSE; + + GtkWidget *t = GTK_WIDGET(gobj()); + + /* Create components */ + for (i = 0; i < static_cast<gint>(G_N_ELEMENTS(_a)); i++) { + /* Label */ + _l[i] = gtk_label_new(""); + gtk_misc_set_alignment(GTK_MISC(_l[i]), 1.0, 0.5); + gtk_widget_show(_l[i]); + +#if GTK_CHECK_VERSION(3, 0, 0) + #if GTK_CHECK_VERSION(3, 12, 0) + gtk_widget_set_margin_start(_l[i], XPAD); + gtk_widget_set_margin_end(_l[i], XPAD); + #else + gtk_widget_set_margin_left(_l[i], XPAD); + gtk_widget_set_margin_right(_l[i], XPAD); + #endif + gtk_widget_set_margin_top(_l[i], YPAD); + gtk_widget_set_margin_bottom(_l[i], YPAD); + gtk_grid_attach(GTK_GRID(t), _l[i], 0, i, 1, 1); +#else + gtk_table_attach(GTK_TABLE(t), _l[i], 0, 1, i, i + 1, GTK_FILL, GTK_FILL, XPAD, YPAD); +#endif + + /* Adjustment */ + _a[i] = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, _rangeLimit, 1.0, 10.0, 10.0)); + /* Slider */ + _s[i] = Gtk::manage(new Inkscape::UI::Widget::ColorSlider(Glib::wrap(_a[i], true))); + _s[i]->show(); + +#if GTK_CHECK_VERSION(3, 0, 0) + #if GTK_CHECK_VERSION(3, 12, 0) + _s[i]->set_margin_start(XPAD); + _s[i]->set_margin_end(XPAD); + #else + _s[i]->set_margin_left(XPAD); + _s[i]->set_margin_right(XPAD); + #endif + _s[i]->set_margin_top(YPAD); + _s[i]->set_margin_bottom(YPAD); + _s[i]->set_hexpand(true); + gtk_grid_attach(GTK_GRID(t), _s[i]->gobj(), 1, i, 1, 1); +#else + gtk_table_attach(GTK_TABLE(t), _s[i]->gobj(), 1, 2, i, i + 1, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), + GTK_FILL, XPAD, YPAD); +#endif + + /* Spinbutton */ + _b[i] = gtk_spin_button_new(GTK_ADJUSTMENT(_a[i]), 1.0, 0); + sp_dialog_defocus_on_enter(_b[i]); + gtk_label_set_mnemonic_widget(GTK_LABEL(_l[i]), _b[i]); + gtk_widget_show(_b[i]); + +#if GTK_CHECK_VERSION(3, 0, 0) + #if GTK_CHECK_VERSION(3, 12, 0) + gtk_widget_set_margin_start(_b[i], XPAD); + gtk_widget_set_margin_end(_b[i], XPAD); + #else + gtk_widget_set_margin_left(_b[i], XPAD); + gtk_widget_set_margin_right(_b[i], XPAD); + #endif + gtk_widget_set_margin_top(_b[i], YPAD); + gtk_widget_set_margin_bottom(_b[i], YPAD); + gtk_widget_set_halign(_b[i], GTK_ALIGN_CENTER); + gtk_widget_set_valign(_b[i], GTK_ALIGN_CENTER); + gtk_grid_attach(GTK_GRID(t), _b[i], 2, i, 1, 1); +#else + gtk_table_attach(GTK_TABLE(t), _b[i], 2, 3, i, i + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, XPAD, YPAD); +#endif + + /* Attach channel value to adjustment */ + g_object_set_data(G_OBJECT(_a[i]), "channel", GINT_TO_POINTER(i)); + /* Signals */ + g_signal_connect(G_OBJECT(_a[i]), "value_changed", G_CALLBACK(_adjustmentAnyChanged), this); + _s[i]->signal_grabbed.connect(sigc::mem_fun(this, &ColorScales::_sliderAnyGrabbed)); + _s[i]->signal_released.connect(sigc::mem_fun(this, &ColorScales::_sliderAnyReleased)); + _s[i]->signal_value_changed.connect(sigc::mem_fun(this, &ColorScales::_sliderAnyChanged)); + } + + //Prevent 5th bar from being shown by PanelDialog::show_all_children + gtk_widget_set_no_show_all(_l[4], TRUE); + _s[4]->set_no_show_all(true); + gtk_widget_set_no_show_all(_b[4], TRUE); + + /* Initial mode is none, so it works */ + setMode(mode); +} + +void ColorScales::_recalcColor() +{ + SPColor color; + gfloat alpha = 1.0; + gfloat c[5]; + + switch (_mode) { + case SP_COLOR_SCALES_MODE_RGB: + case SP_COLOR_SCALES_MODE_HSV: + _getRgbaFloatv(c); + color.set(c[0], c[1], c[2]); + alpha = c[3]; + break; + case SP_COLOR_SCALES_MODE_CMYK: { + _getCmykaFloatv(c); + + float rgb[3]; + sp_color_cmyk_to_rgb_floatv(rgb, c[0], c[1], c[2], c[3]); + color.set(rgb[0], rgb[1], rgb[2]); + alpha = c[4]; + break; + } + default: + g_warning("file %s: line %d: Illegal color selector mode %d", __FILE__, __LINE__, _mode); + break; + } + + _color.preserveICC(); + _color.setColorAlpha(color, alpha); +} + +void ColorScales::_updateDisplay() +{ +#ifdef DUMP_CHANGE_INFO + g_message("ColorScales::_onColorChanged( this=%p, %f, %f, %f, %f)", this, _color.color().v.c[0], + _color.color().v.c[1], _color.color().v.c[2], _color.alpha()); +#endif + gfloat tmp[3]; + gfloat c[5] = { 0.0, 0.0, 0.0, 0.0 }; + + SPColor color = _color.color(); + + switch (_mode) { + case SP_COLOR_SCALES_MODE_RGB: + sp_color_get_rgb_floatv(&color, c); + c[3] = _color.alpha(); + c[4] = 0.0; + break; + case SP_COLOR_SCALES_MODE_HSV: + sp_color_get_rgb_floatv(&color, tmp); + sp_color_rgb_to_hsl_floatv(c, tmp[0], tmp[1], tmp[2]); + c[3] = _color.alpha(); + c[4] = 0.0; + break; + case SP_COLOR_SCALES_MODE_CMYK: + sp_color_get_cmyk_floatv(&color, c); + c[4] = _color.alpha(); + break; + default: + g_warning("file %s: line %d: Illegal color selector mode %d", __FILE__, __LINE__, _mode); + break; + } + + _updating = TRUE; + setScaled(_a[0], c[0]); + setScaled(_a[1], c[1]); + setScaled(_a[2], c[2]); + setScaled(_a[3], c[3]); + setScaled(_a[4], c[4]); + _updateSliders(CSC_CHANNELS_ALL); + _updating = FALSE; +} + +/* Helpers for setting color value */ +gfloat ColorScales::getScaled(const GtkAdjustment *a) +{ + gfloat val = gtk_adjustment_get_value(const_cast<GtkAdjustment *>(a)) / + gtk_adjustment_get_upper(const_cast<GtkAdjustment *>(a)); + return val; +} + +void ColorScales::setScaled(GtkAdjustment *a, gfloat v) +{ + gfloat val = v * gtk_adjustment_get_upper(a); + gtk_adjustment_set_value(a, val); +} + +void ColorScales::_setRangeLimit(gdouble upper) +{ + _rangeLimit = upper; + for (gint i = 0; i < static_cast<gint>(G_N_ELEMENTS(_a)); i++) { + gtk_adjustment_set_upper(_a[i], upper); + gtk_adjustment_changed(_a[i]); + } +} + +void ColorScales::_onColorChanged() +{ + if (!get_visible()) { + return; + } + _updateDisplay(); +} + +void ColorScales::on_show() +{ +#if GTK_CHECK_VERSION(3, 0, 0) + Gtk::Grid::on_show(); +#else + Gtk::Table::on_show(); +#endif + _updateDisplay(); +} + +void ColorScales::_getRgbaFloatv(gfloat *rgba) +{ + g_return_if_fail(rgba != NULL); + + switch (_mode) { + case SP_COLOR_SCALES_MODE_RGB: + rgba[0] = getScaled(_a[0]); + rgba[1] = getScaled(_a[1]); + rgba[2] = getScaled(_a[2]); + rgba[3] = getScaled(_a[3]); + break; + case SP_COLOR_SCALES_MODE_HSV: + sp_color_hsl_to_rgb_floatv(rgba, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2])); + rgba[3] = getScaled(_a[3]); + break; + case SP_COLOR_SCALES_MODE_CMYK: + sp_color_cmyk_to_rgb_floatv(rgba, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), getScaled(_a[3])); + rgba[3] = getScaled(_a[4]); + break; + default: + g_warning("file %s: line %d: Illegal color selector mode", __FILE__, __LINE__); + break; + } +} + +void ColorScales::_getCmykaFloatv(gfloat *cmyka) +{ + gfloat rgb[3]; + + g_return_if_fail(cmyka != NULL); + + switch (_mode) { + case SP_COLOR_SCALES_MODE_RGB: + sp_color_rgb_to_cmyk_floatv(cmyka, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2])); + cmyka[4] = getScaled(_a[3]); + break; + case SP_COLOR_SCALES_MODE_HSV: + sp_color_hsl_to_rgb_floatv(rgb, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2])); + sp_color_rgb_to_cmyk_floatv(cmyka, rgb[0], rgb[1], rgb[2]); + cmyka[4] = getScaled(_a[3]); + break; + case SP_COLOR_SCALES_MODE_CMYK: + cmyka[0] = getScaled(_a[0]); + cmyka[1] = getScaled(_a[1]); + cmyka[2] = getScaled(_a[2]); + cmyka[3] = getScaled(_a[3]); + cmyka[4] = getScaled(_a[4]); + break; + default: + g_warning("file %s: line %d: Illegal color selector mode", __FILE__, __LINE__); + break; + } +} + +guint32 ColorScales::_getRgba32() +{ + gfloat c[4]; + guint32 rgba; + + _getRgbaFloatv(c); + + rgba = SP_RGBA32_F_COMPOSE(c[0], c[1], c[2], c[3]); + + return rgba; +} + +void ColorScales::setMode(SPColorScalesMode mode) +{ + gfloat rgba[4]; + gfloat c[4]; + + if (_mode == mode) + return; + + if ((_mode == SP_COLOR_SCALES_MODE_RGB) || (_mode == SP_COLOR_SCALES_MODE_HSV) || + (_mode == SP_COLOR_SCALES_MODE_CMYK)) { + _getRgbaFloatv(rgba); + } + else { + rgba[0] = rgba[1] = rgba[2] = rgba[3] = 1.0; + } + + _mode = mode; + + switch (mode) { + case SP_COLOR_SCALES_MODE_RGB: + _setRangeLimit(255.0); + gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[0]), _("_R:")); + _s[0]->set_tooltip_text(_("Red")); + gtk_widget_set_tooltip_text(_b[0], _("Red")); + gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[1]), _("_G:")); + _s[1]->set_tooltip_text(_("Green")); + gtk_widget_set_tooltip_text(_b[1], _("Green")); + gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[2]), _("_B:")); + _s[2]->set_tooltip_text(_("Blue")); + gtk_widget_set_tooltip_text(_b[2], _("Blue")); + gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[3]), _("_A:")); + _s[3]->set_tooltip_text(_("Alpha (opacity)")); + gtk_widget_set_tooltip_text(_b[3], _("Alpha (opacity)")); + _s[0]->setMap(NULL); + gtk_widget_hide(_l[4]); + _s[4]->hide(); + gtk_widget_hide(_b[4]); + _updating = TRUE; + setScaled(_a[0], rgba[0]); + setScaled(_a[1], rgba[1]); + setScaled(_a[2], rgba[2]); + setScaled(_a[3], rgba[3]); + _updateSliders(CSC_CHANNELS_ALL); + _updating = FALSE; + break; + case SP_COLOR_SCALES_MODE_HSV: + _setRangeLimit(255.0); + gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[0]), _("_H:")); + _s[0]->set_tooltip_text(_("Hue")); + gtk_widget_set_tooltip_text(_b[0], _("Hue")); + gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[1]), _("_S:")); + _s[1]->set_tooltip_text(_("Saturation")); + gtk_widget_set_tooltip_text(_b[1], _("Saturation")); + gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[2]), _("_L:")); + _s[2]->set_tooltip_text(_("Lightness")); + gtk_widget_set_tooltip_text(_b[2], _("Lightness")); + gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[3]), _("_A:")); + _s[3]->set_tooltip_text(_("Alpha (opacity)")); + gtk_widget_set_tooltip_text(_b[3], _("Alpha (opacity)")); + _s[0]->setMap((guchar *)(sp_color_scales_hue_map())); + gtk_widget_hide(_l[4]); + _s[4]->hide(); + gtk_widget_hide(_b[4]); + _updating = TRUE; + c[0] = 0.0; + sp_color_rgb_to_hsl_floatv(c, rgba[0], rgba[1], rgba[2]); + setScaled(_a[0], c[0]); + setScaled(_a[1], c[1]); + setScaled(_a[2], c[2]); + setScaled(_a[3], rgba[3]); + _updateSliders(CSC_CHANNELS_ALL); + _updating = FALSE; + break; + case SP_COLOR_SCALES_MODE_CMYK: + _setRangeLimit(100.0); + gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[0]), _("_C:")); + _s[0]->set_tooltip_text(_("Cyan")); + gtk_widget_set_tooltip_text(_b[0], _("Cyan")); + gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[1]), _("_M:")); + _s[1]->set_tooltip_text(_("Magenta")); + gtk_widget_set_tooltip_text(_b[1], _("Magenta")); + gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[2]), _("_Y:")); + _s[2]->set_tooltip_text(_("Yellow")); + gtk_widget_set_tooltip_text(_b[2], _("Yellow")); + gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[3]), _("_K:")); + _s[3]->set_tooltip_text(_("Black")); + gtk_widget_set_tooltip_text(_b[3], _("Black")); + gtk_label_set_markup_with_mnemonic(GTK_LABEL(_l[4]), _("_A:")); + _s[4]->set_tooltip_text(_("Alpha (opacity)")); + gtk_widget_set_tooltip_text(_b[4], _("Alpha (opacity)")); + _s[0]->setMap(NULL); + gtk_widget_show(_l[4]); + _s[4]->show(); + gtk_widget_show(_b[4]); + _updating = TRUE; + + sp_color_rgb_to_cmyk_floatv(c, rgba[0], rgba[1], rgba[2]); + setScaled(_a[0], c[0]); + setScaled(_a[1], c[1]); + setScaled(_a[2], c[2]); + setScaled(_a[3], c[3]); + + setScaled(_a[4], rgba[3]); + _updateSliders(CSC_CHANNELS_ALL); + _updating = FALSE; + break; + default: + g_warning("file %s: line %d: Illegal color selector mode", __FILE__, __LINE__); + break; + } +} + +SPColorScalesMode ColorScales::getMode() const { return _mode; } + +void ColorScales::_adjustmentAnyChanged(GtkAdjustment *adjustment, ColorScales *cs) +{ + gint channel = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(adjustment), "channel")); + + _adjustmentChanged(cs, channel); +} + +void ColorScales::_sliderAnyGrabbed() +{ + if (_updating) { + return; + } + if (!_dragging) { + _dragging = TRUE; + _color.setHeld(true); + } +} + +void ColorScales::_sliderAnyReleased() +{ + if (_updating) { + return; + } + if (_dragging) { + _dragging = FALSE; + _color.setHeld(false); + } +} + +void ColorScales::_sliderAnyChanged() +{ + if (_updating) { + return; + } + _recalcColor(); +} + +void ColorScales::_adjustmentChanged(ColorScales *scales, guint channel) +{ + if (scales->_updating) { + return; + } + + scales->_updateSliders((1 << channel)); + scales->_recalcColor(); +} + +void ColorScales::_updateSliders(guint channels) +{ + gfloat rgb0[3], rgbm[3], rgb1[3]; +#ifdef SPCS_PREVIEW + guint32 rgba; +#endif + switch (_mode) { + case SP_COLOR_SCALES_MODE_RGB: + if ((channels != CSC_CHANNEL_R) && (channels != CSC_CHANNEL_A)) { + /* Update red */ + _s[0]->setColors(SP_RGBA32_F_COMPOSE(0.0, getScaled(_a[1]), getScaled(_a[2]), 1.0), + SP_RGBA32_F_COMPOSE(0.5, getScaled(_a[1]), getScaled(_a[2]), 1.0), + SP_RGBA32_F_COMPOSE(1.0, getScaled(_a[1]), getScaled(_a[2]), 1.0)); + } + if ((channels != CSC_CHANNEL_G) && (channels != CSC_CHANNEL_A)) { + /* Update green */ + _s[1]->setColors(SP_RGBA32_F_COMPOSE(getScaled(_a[0]), 0.0, getScaled(_a[2]), 1.0), + SP_RGBA32_F_COMPOSE(getScaled(_a[0]), 0.5, getScaled(_a[2]), 1.0), + SP_RGBA32_F_COMPOSE(getScaled(_a[0]), 1.0, getScaled(_a[2]), 1.0)); + } + if ((channels != CSC_CHANNEL_B) && (channels != CSC_CHANNEL_A)) { + /* Update blue */ + _s[2]->setColors(SP_RGBA32_F_COMPOSE(getScaled(_a[0]), getScaled(_a[1]), 0.0, 1.0), + SP_RGBA32_F_COMPOSE(getScaled(_a[0]), getScaled(_a[1]), 0.5, 1.0), + SP_RGBA32_F_COMPOSE(getScaled(_a[0]), getScaled(_a[1]), 1.0, 1.0)); + } + if (channels != CSC_CHANNEL_A) { + /* Update alpha */ + _s[3]->setColors(SP_RGBA32_F_COMPOSE(getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), 0.0), + SP_RGBA32_F_COMPOSE(getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), 0.5), + SP_RGBA32_F_COMPOSE(getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), 1.0)); + } + break; + case SP_COLOR_SCALES_MODE_HSV: + /* Hue is never updated */ + if ((channels != CSC_CHANNEL_S) && (channels != CSC_CHANNEL_A)) { + /* Update saturation */ + sp_color_hsl_to_rgb_floatv(rgb0, getScaled(_a[0]), 0.0, getScaled(_a[2])); + sp_color_hsl_to_rgb_floatv(rgbm, getScaled(_a[0]), 0.5, getScaled(_a[2])); + sp_color_hsl_to_rgb_floatv(rgb1, getScaled(_a[0]), 1.0, getScaled(_a[2])); + _s[1]->setColors(SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 1.0), + SP_RGBA32_F_COMPOSE(rgbm[0], rgbm[1], rgbm[2], 1.0), + SP_RGBA32_F_COMPOSE(rgb1[0], rgb1[1], rgb1[2], 1.0)); + } + if ((channels != CSC_CHANNEL_V) && (channels != CSC_CHANNEL_A)) { + /* Update value */ + sp_color_hsl_to_rgb_floatv(rgb0, getScaled(_a[0]), getScaled(_a[1]), 0.0); + sp_color_hsl_to_rgb_floatv(rgbm, getScaled(_a[0]), getScaled(_a[1]), 0.5); + sp_color_hsl_to_rgb_floatv(rgb1, getScaled(_a[0]), getScaled(_a[1]), 1.0); + _s[2]->setColors(SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 1.0), + SP_RGBA32_F_COMPOSE(rgbm[0], rgbm[1], rgbm[2], 1.0), + SP_RGBA32_F_COMPOSE(rgb1[0], rgb1[1], rgb1[2], 1.0)); + } + if (channels != CSC_CHANNEL_A) { + /* Update alpha */ + sp_color_hsl_to_rgb_floatv(rgb0, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2])); + _s[3]->setColors(SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 0.0), + SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 0.5), + SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 1.0)); + } + break; + case SP_COLOR_SCALES_MODE_CMYK: + if ((channels != CSC_CHANNEL_C) && (channels != CSC_CHANNEL_CMYKA)) { + /* Update C */ + sp_color_cmyk_to_rgb_floatv(rgb0, 0.0, getScaled(_a[1]), getScaled(_a[2]), getScaled(_a[3])); + sp_color_cmyk_to_rgb_floatv(rgbm, 0.5, getScaled(_a[1]), getScaled(_a[2]), getScaled(_a[3])); + sp_color_cmyk_to_rgb_floatv(rgb1, 1.0, getScaled(_a[1]), getScaled(_a[2]), getScaled(_a[3])); + _s[0]->setColors(SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 1.0), + SP_RGBA32_F_COMPOSE(rgbm[0], rgbm[1], rgbm[2], 1.0), + SP_RGBA32_F_COMPOSE(rgb1[0], rgb1[1], rgb1[2], 1.0)); + } + if ((channels != CSC_CHANNEL_M) && (channels != CSC_CHANNEL_CMYKA)) { + /* Update M */ + sp_color_cmyk_to_rgb_floatv(rgb0, getScaled(_a[0]), 0.0, getScaled(_a[2]), getScaled(_a[3])); + sp_color_cmyk_to_rgb_floatv(rgbm, getScaled(_a[0]), 0.5, getScaled(_a[2]), getScaled(_a[3])); + sp_color_cmyk_to_rgb_floatv(rgb1, getScaled(_a[0]), 1.0, getScaled(_a[2]), getScaled(_a[3])); + _s[1]->setColors(SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 1.0), + SP_RGBA32_F_COMPOSE(rgbm[0], rgbm[1], rgbm[2], 1.0), + SP_RGBA32_F_COMPOSE(rgb1[0], rgb1[1], rgb1[2], 1.0)); + } + if ((channels != CSC_CHANNEL_Y) && (channels != CSC_CHANNEL_CMYKA)) { + /* Update Y */ + sp_color_cmyk_to_rgb_floatv(rgb0, getScaled(_a[0]), getScaled(_a[1]), 0.0, getScaled(_a[3])); + sp_color_cmyk_to_rgb_floatv(rgbm, getScaled(_a[0]), getScaled(_a[1]), 0.5, getScaled(_a[3])); + sp_color_cmyk_to_rgb_floatv(rgb1, getScaled(_a[0]), getScaled(_a[1]), 1.0, getScaled(_a[3])); + _s[2]->setColors(SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 1.0), + SP_RGBA32_F_COMPOSE(rgbm[0], rgbm[1], rgbm[2], 1.0), + SP_RGBA32_F_COMPOSE(rgb1[0], rgb1[1], rgb1[2], 1.0)); + } + if ((channels != CSC_CHANNEL_K) && (channels != CSC_CHANNEL_CMYKA)) { + /* Update K */ + sp_color_cmyk_to_rgb_floatv(rgb0, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), 0.0); + sp_color_cmyk_to_rgb_floatv(rgbm, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), 0.5); + sp_color_cmyk_to_rgb_floatv(rgb1, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), 1.0); + _s[3]->setColors(SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 1.0), + SP_RGBA32_F_COMPOSE(rgbm[0], rgbm[1], rgbm[2], 1.0), + SP_RGBA32_F_COMPOSE(rgb1[0], rgb1[1], rgb1[2], 1.0)); + } + if (channels != CSC_CHANNEL_CMYKA) { + /* Update alpha */ + sp_color_cmyk_to_rgb_floatv(rgb0, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), + getScaled(_a[3])); + _s[4]->setColors(SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 0.0), + SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 0.5), + SP_RGBA32_F_COMPOSE(rgb0[0], rgb0[1], rgb0[2], 1.0)); + } + break; + default: + g_warning("file %s: line %d: Illegal color selector mode", __FILE__, __LINE__); + break; + } + +#ifdef SPCS_PREVIEW + rgba = sp_color_scales_get_rgba32(cs); + sp_color_preview_set_rgba32(SP_COLOR_PREVIEW(_p), rgba); +#endif +} + +static const gchar *sp_color_scales_hue_map(void) +{ + static gchar *map = NULL; + + if (!map) { + gchar *p; + gint h; + map = g_new(gchar, 4 * 1024); + p = map; + for (h = 0; h < 1024; h++) { + gfloat rgb[3]; + sp_color_hsl_to_rgb_floatv(rgb, h / 1024.0, 1.0, 0.5); + *p++ = SP_COLOR_F_TO_U(rgb[0]); + *p++ = SP_COLOR_F_TO_U(rgb[1]); + *p++ = SP_COLOR_F_TO_U(rgb[2]); + *p++ = 255; + } + } + + return map; +} + +ColorScalesFactory::ColorScalesFactory(SPColorScalesMode submode) + : _submode(submode) +{ +} + +ColorScalesFactory::~ColorScalesFactory() {} + +Gtk::Widget *ColorScalesFactory::createWidget(Inkscape::UI::SelectedColor &color) const +{ + Gtk::Widget *w = Gtk::manage(new ColorScales(color, _submode)); + return w; +} + +Glib::ustring ColorScalesFactory::modeName() const { + return gettext(ColorScales::SUBMODE_NAMES[_submode]); +} + +} +} +} diff --git a/src/ui/widget/color-scales.h b/src/ui/widget/color-scales.h new file mode 100644 index 000000000..aeacfbcc1 --- /dev/null +++ b/src/ui/widget/color-scales.h @@ -0,0 +1,112 @@ +#ifndef SEEN_SP_COLOR_SCALES_H +#define SEEN_SP_COLOR_SCALES_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#if WITH_GTKMM_3_0 +#include <gtkmm/grid.h> +#else +#include <gtkmm/table.h> +#endif + +#include "ui/selected-color.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +class ColorSlider; + +typedef enum { + SP_COLOR_SCALES_MODE_NONE = 0, + SP_COLOR_SCALES_MODE_RGB = 1, + SP_COLOR_SCALES_MODE_HSV = 2, + SP_COLOR_SCALES_MODE_CMYK = 3 +} SPColorScalesMode; + +class ColorScales +#if GTK_CHECK_VERSION(3, 0, 0) + : public Gtk::Grid +#else + : public Gtk::Table +#endif +{ +public: + static const gchar *SUBMODE_NAMES[]; + + static gfloat getScaled(const GtkAdjustment *a); + static void setScaled(GtkAdjustment *a, gfloat v); + + ColorScales(SelectedColor &color, SPColorScalesMode mode); + virtual ~ColorScales(); + + virtual void _initUI(SPColorScalesMode mode); + + void setMode(SPColorScalesMode mode); + SPColorScalesMode getMode() const; + +protected: + void _onColorChanged(); + void on_show(); + + static void _adjustmentAnyChanged(GtkAdjustment *adjustment, ColorScales *cs); + void _sliderAnyGrabbed(); + void _sliderAnyReleased(); + void _sliderAnyChanged(); + static void _adjustmentChanged(ColorScales *cs, guint channel); + + void _getRgbaFloatv(gfloat *rgba); + void _getCmykaFloatv(gfloat *cmyka); + guint32 _getRgba32(); + void _updateSliders(guint channels); + void _recalcColor(); + void _updateDisplay(); + + void _setRangeLimit(gdouble upper); + + SelectedColor &_color; + SPColorScalesMode _mode; + gdouble _rangeLimit; + gboolean _updating : 1; + gboolean _dragging : 1; + GtkAdjustment *_a[5]; /* Channel adjustments */ + Inkscape::UI::Widget::ColorSlider *_s[5]; /* Channel sliders */ + GtkWidget *_b[5]; /* Spinbuttons */ + GtkWidget *_l[5]; /* Labels */ + +private: + // By default, disallow copy constructor and assignment operator + ColorScales(ColorScales const &obj); + ColorScales &operator=(ColorScales const &obj); +}; + +class ColorScalesFactory : public Inkscape::UI::ColorSelectorFactory +{ +public: + ColorScalesFactory(SPColorScalesMode submode); + ~ColorScalesFactory(); + + Gtk::Widget *createWidget(Inkscape::UI::SelectedColor &color) const; + Glib::ustring modeName() const; + +private: + SPColorScalesMode _submode; +}; + +} +} +} + +#endif /* !SEEN_SP_COLOR_SCALES_H */ +/* + 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 : diff --git a/src/ui/widget/color-slider.cpp b/src/ui/widget/color-slider.cpp new file mode 100644 index 000000000..0c9586a67 --- /dev/null +++ b/src/ui/widget/color-slider.cpp @@ -0,0 +1,633 @@ +/** + * @file + * A slider with colored background - implementation. + */ +/* Author: + * Lauris Kaplinski <lauris@kaplinski.com> + * bulia byak <buliabyak@users.sf.net> + * + * Copyright (C) 2001-2002 Lauris Kaplinski + * + * This code is in public domain + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gdkmm/cursor.h> +#include <gdkmm/screen.h> +#include <gdkmm/general.h> +#include <gtkmm/adjustment.h> +#if WITH_GTKMM_3_0 +#include <gtkmm/stylecontext.h> +#else +#include <gtkmm/style.h> +#endif +#include <gtk/gtk.h> + +#include "ui/widget/color-scales.h" +#include "ui/widget/color-slider.h" +#include "preferences.h" + +static const gint SLIDER_WIDTH = 96; +static const gint SLIDER_HEIGHT = 8; +static const gint ARROW_SIZE = 7; + +static const guchar *sp_color_slider_render_gradient(gint x0, gint y0, gint width, gint height, gint c[], gint dc[], + guint b0, guint b1, guint mask); +static const guchar *sp_color_slider_render_map(gint x0, gint y0, gint width, gint height, guchar *map, gint start, + gint step, guint b0, guint b1, guint mask); + +namespace Inkscape { +namespace UI { +namespace Widget { + +#if GTK_CHECK_VERSION(3, 0, 0) +ColorSlider::ColorSlider(Glib::RefPtr<Gtk::Adjustment> adjustment) + : _dragging(false) +#else +ColorSlider::ColorSlider(Gtk::Adjustment *adjustment) + : _dragging(false) + , _adjustment(NULL) +#endif + , _value(0.0) + , _oldvalue(0.0) + , _mapsize(0) + , _map(NULL) +{ + _c0[0] = 0x00; + _c0[1] = 0x00; + _c0[2] = 0x00; + _c0[3] = 0xff; + + _cm[0] = 0xff; + _cm[1] = 0x00; + _cm[2] = 0x00; + _cm[3] = 0xff; + + _c0[0] = 0xff; + _c0[1] = 0xff; + _c0[2] = 0xff; + _c0[3] = 0xff; + + _b0 = 0x5f; + _b1 = 0xa0; + _bmask = 0x08; + + setAdjustment(adjustment); +} + +ColorSlider::~ColorSlider() +{ + if (_adjustment) { + _adjustment_changed_connection.disconnect(); + _adjustment_value_changed_connection.disconnect(); +#if GTK_CHECK_VERSION(3, 0, 0) + _adjustment.reset(); +#else + _adjustment->unreference(); + _adjustment = NULL; +#endif + } +} + +void ColorSlider::on_realize() +{ + set_realized(); + + if (!_gdk_window) { + GdkWindowAttr attributes; + gint attributes_mask; + Gtk::Allocation allocation = get_allocation(); + + memset(&attributes, 0, sizeof(attributes)); + attributes.x = allocation.get_x(); + attributes.y = allocation.get_y(); + attributes.width = allocation.get_width(); + attributes.height = allocation.get_height(); + attributes.window_type = GDK_WINDOW_CHILD; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.visual = gdk_screen_get_system_visual(gdk_screen_get_default()); +#if !GTK_CHECK_VERSION(3, 0, 0) + attributes.colormap = gdk_screen_get_system_colormap(gdk_screen_get_default()); +#endif + attributes.event_mask = get_events(); + attributes.event_mask |= (Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | + Gdk::POINTER_MOTION_MASK | Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK); + +#if GTK_CHECK_VERSION(3, 0, 0) + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL; +#else + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; +#endif + + _gdk_window = Gdk::Window::create(get_parent_window(), &attributes, attributes_mask); + set_window(_gdk_window); + _gdk_window->set_user_data(gobj()); + +#if !GTK_CHECK_VERSION(3, 0, 0) + style_attach(); +#endif + } +} + +void ColorSlider::on_unrealize() +{ + _gdk_window.reset(); + + Gtk::Widget::on_unrealize(); +} + +void ColorSlider::on_size_allocate(Gtk::Allocation &allocation) +{ + set_allocation(allocation); + + if (get_realized()) { + _gdk_window->move_resize(allocation.get_x(), allocation.get_y(), allocation.get_width(), + allocation.get_height()); + } +} + +#if GTK_CHECK_VERSION(3, 0, 0) + +void ColorSlider::get_preferred_width_vfunc(int &minimum_width, int &natural_width) const +{ + Glib::RefPtr<Gtk::StyleContext> style_context = get_style_context(); + Gtk::Border padding = style_context->get_padding(get_state_flags()); + int width = SLIDER_WIDTH + padding.get_left() + padding.get_right(); + minimum_width = natural_width = width; +} + +void ColorSlider::get_preferred_width_for_height_vfunc(int /*height*/, int &minimum_width, int &natural_width) const +{ + get_preferred_width(minimum_width, natural_width); +} + +void ColorSlider::get_preferred_height_vfunc(int &minimum_height, int &natural_height) const +{ + Glib::RefPtr<Gtk::StyleContext> style_context = get_style_context(); + Gtk::Border padding = style_context->get_padding(get_state_flags()); + int height = SLIDER_HEIGHT + padding.get_top() + padding.get_bottom(); + minimum_height = natural_height = height; +} + +void ColorSlider::get_preferred_height_for_width_vfunc(int /*width*/, int &minimum_height, int &natural_height) const +{ + get_preferred_height(minimum_height, natural_height); +} + +#else + +void ColorSlider::on_size_request(Gtk::Requisition *requisition) +{ + GtkStyle *style = gtk_widget_get_style(gobj()); + requisition->width = SLIDER_WIDTH + style->xthickness * 2; + requisition->height = SLIDER_HEIGHT + style->ythickness * 2; +} + +bool ColorSlider::on_expose_event(GdkEventExpose *event) +{ + bool result = false; + + if (get_is_drawable()) { + Cairo::RefPtr<Cairo::Context> cr = _gdk_window->create_cairo_context(); + result = on_draw(cr); + } + return result; +} + +#endif + +bool ColorSlider::on_button_press_event(GdkEventButton *event) +{ + if (event->button == 1) { + Gtk::Allocation allocation = get_allocation(); + gint cx, cw; +#if GTK_CHECK_VERSION(3, 0, 0) + cx = get_style_context()->get_padding(get_state_flags()).get_left(); +#else + cx = get_style()->get_xthickness(); +#endif + cw = allocation.get_width() - 2 * cx; + signal_grabbed.emit(); + _dragging = true; + _oldvalue = _value; + ColorScales::setScaled(_adjustment->gobj(), CLAMP((gfloat)(event->x - cx) / cw, 0.0, 1.0)); + signal_dragged.emit(); + +#if GTK_CHECK_VERSION(3, 0, 0) + gdk_device_grab( + gdk_event_get_device(reinterpret_cast<GdkEvent *>(event)), _gdk_window->gobj(), GDK_OWNERSHIP_NONE, FALSE, + static_cast<GdkEventMask>(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK), NULL, event->time); +#else + gdk_pointer_grab(get_window()->gobj(), FALSE, + static_cast<GdkEventMask>(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK), NULL, NULL, + event->time); +#endif + } + + return false; +} + +bool ColorSlider::on_button_release_event(GdkEventButton *event) +{ + if (event->button == 1) { + +#if GTK_CHECK_VERSION(3, 0, 0) + gdk_device_ungrab(gdk_event_get_device(reinterpret_cast<GdkEvent *>(event)), + gdk_event_get_time(reinterpret_cast<GdkEvent *>(event))); +#else + get_window()->pointer_ungrab(event->time); +#endif + + _dragging = false; + signal_released.emit(); + if (_value != _oldvalue) { + signal_value_changed.emit(); + } + } + + return false; +} + +bool ColorSlider::on_motion_notify_event(GdkEventMotion *event) +{ + if (_dragging) { + gint cx, cw; + Gtk::Allocation allocation = get_allocation(); +#if GTK_CHECK_VERSION(3, 0, 0) + cx = get_style_context()->get_padding(get_state_flags()).get_left(); +#else + cx = get_style()->get_xthickness(); +#endif + cw = allocation.get_width() - 2 * cx; + ColorScales::setScaled(_adjustment->gobj(), CLAMP((gfloat)(event->x - cx) / cw, 0.0, 1.0)); + signal_dragged.emit(); + } + + return false; +} + +#if GTK_CHECK_VERSION(3, 0, 0) +void ColorSlider::setAdjustment(Glib::RefPtr<Gtk::Adjustment> adjustment) +{ +#else +void ColorSlider::setAdjustment(Gtk::Adjustment *adjustment) +{ +#endif + if (!adjustment) { +#if GTK_CHECK_VERSION(3, 0, 0) + _adjustment = Gtk::Adjustment::create(0.0, 0.0, 1.0, 0.01, 0.0, 0.0); +#else + _adjustment = Gtk::manage(new Gtk::Adjustment(0.0, 0.0, 1.0, 0.01, 0.0, 0.0)); +#endif + } + else { + adjustment->set_page_increment(0.0); + adjustment->set_page_size(0.0); + } + + if (_adjustment != adjustment) { + if (_adjustment) { + _adjustment_changed_connection.disconnect(); + _adjustment_value_changed_connection.disconnect(); +#if !GTK_CHECK_VERSION(3, 0, 0) + _adjustment->unreference(); +#endif + } + + _adjustment = adjustment; + _adjustment_changed_connection = + _adjustment->signal_changed().connect(sigc::mem_fun(this, &ColorSlider::_onAdjustmentChanged)); + _adjustment_value_changed_connection = + _adjustment->signal_value_changed().connect(sigc::mem_fun(this, &ColorSlider::_onAdjustmentValueChanged)); + + _value = ColorScales::getScaled(_adjustment->gobj()); + + _onAdjustmentChanged(); + } +} + +void ColorSlider::_onAdjustmentChanged() { queue_draw(); } + +void ColorSlider::_onAdjustmentValueChanged() +{ + if (_value != ColorScales::getScaled(_adjustment->gobj())) { + gint cx, cy, cw, ch; +#if GTK_CHECK_VERSION(3, 0, 0) + Glib::RefPtr<Gtk::StyleContext> style_context = get_style_context(); + Gtk::Allocation allocation = get_allocation(); + Gtk::Border padding = style_context->get_padding(get_state_flags()); + cx = padding.get_left(); + cy = padding.get_top(); +#else + Glib::RefPtr<Gtk::Style> style = get_style(); + Gtk::Allocation allocation = get_allocation(); + cx = style->get_xthickness(); + cy = style->get_ythickness(); +#endif + cw = allocation.get_width() - 2 * cx; + ch = allocation.get_height() - 2 * cy; + if ((gint)(ColorScales::getScaled(_adjustment->gobj()) * cw) != (gint)(_value * cw)) { + gint ax, ay; + gfloat value; + value = _value; + _value = ColorScales::getScaled(_adjustment->gobj()); + ax = (int)(cx + value * cw - ARROW_SIZE / 2 - 2); + ay = cy; + queue_draw_area(ax, ay, ARROW_SIZE + 4, ch); + ax = (int)(cx + _value * cw - ARROW_SIZE / 2 - 2); + ay = cy; + queue_draw_area(ax, ay, ARROW_SIZE + 4, ch); + } + else { + _value = ColorScales::getScaled(_adjustment->gobj()); + } + } +} + +void ColorSlider::setColors(guint32 start, guint32 mid, guint32 end) +{ + // Remove any map, if set + _map = 0; + + _c0[0] = start >> 24; + _c0[1] = (start >> 16) & 0xff; + _c0[2] = (start >> 8) & 0xff; + _c0[3] = start & 0xff; + + _cm[0] = mid >> 24; + _cm[1] = (mid >> 16) & 0xff; + _cm[2] = (mid >> 8) & 0xff; + _cm[3] = mid & 0xff; + + _c1[0] = end >> 24; + _c1[1] = (end >> 16) & 0xff; + _c1[2] = (end >> 8) & 0xff; + _c1[3] = end & 0xff; + + queue_draw(); +} + +void ColorSlider::setMap(const guchar *map) +{ + _map = const_cast<guchar *>(map); + + queue_draw(); +} + +void ColorSlider::setBackground(guint dark, guint light, guint size) +{ + _b0 = dark; + _b1 = light; + _bmask = size; + + queue_draw(); +} + +bool ColorSlider::on_draw(const Cairo::RefPtr<Cairo::Context> &cr) +{ + gboolean colorsOnTop = Inkscape::Preferences::get()->getBool("/options/workarounds/colorsontop", false); + + Gtk::Allocation allocation = get_allocation(); + +#if GTK_CHECK_VERSION(3, 0, 0) + Glib::RefPtr<Gtk::StyleContext> style_context = get_style_context(); +#else + Glib::RefPtr<Gdk::Window> window = get_window(); + Glib::RefPtr<Gtk::Style> style = get_style(); +#endif + + // Draw shadow + if (colorsOnTop) { +#if GTK_CHECK_VERSION(3, 0, 0) + style_context->render_frame(cr, 0, 0, allocation.get_width(), allocation.get_height()); +#else + gtk_paint_shadow(style->gobj(), window->gobj(), gtk_widget_get_state(gobj()), GTK_SHADOW_IN, NULL, gobj(), + "colorslider", 0, 0, allocation.get_width(), allocation.get_height()); +#endif + } + + /* Paintable part of color gradient area */ + Gdk::Rectangle carea; + +#if GTK_CHECK_VERSION(3, 0, 0) + Gtk::Border padding; + + padding = style_context->get_padding(get_state_flags()); + + carea.set_x(padding.get_left()); + carea.set_y(padding.get_top()); + ; +#else + carea.set_x(style->get_xthickness()); + carea.set_y(style->get_ythickness()); +#endif + + carea.set_width(allocation.get_width() - 2 * carea.get_x()); + carea.set_height(allocation.get_height() - 2 * carea.get_y()); + + if (_map) { + /* Render map pixelstore */ + gint d = (1024 << 16) / carea.get_width(); + gint s = 0; + + const guchar *b = + sp_color_slider_render_map(0, 0, carea.get_width(), carea.get_height(), _map, s, d, _b0, _b1, _bmask); + + if (b != NULL && carea.get_width() > 0) { + Glib::RefPtr<Gdk::Pixbuf> pb = Gdk::Pixbuf::create_from_data( + b, Gdk::COLORSPACE_RGB, false, 8, carea.get_width(), carea.get_height(), carea.get_width() * 3); + + Gdk::Cairo::set_source_pixbuf(cr, pb, carea.get_x(), carea.get_y()); + cr->paint(); + } + } + else { + gint c[4], dc[4]; + + /* Render gradient */ + + // part 1: from c0 to cm + if (carea.get_width() > 0) { + for (gint i = 0; i < 4; i++) { + c[i] = _c0[i] << 16; + dc[i] = ((_cm[i] << 16) - c[i]) / (carea.get_width() / 2); + } + guint wi = carea.get_width() / 2; + const guchar *b = sp_color_slider_render_gradient(0, 0, wi, carea.get_height(), c, dc, _b0, _b1, _bmask); + + /* Draw pixelstore 1 */ + if (b != NULL && wi > 0) { + Glib::RefPtr<Gdk::Pixbuf> pb = + Gdk::Pixbuf::create_from_data(b, Gdk::COLORSPACE_RGB, false, 8, wi, carea.get_height(), wi * 3); + + Gdk::Cairo::set_source_pixbuf(cr, pb, carea.get_x(), carea.get_y()); + cr->paint(); + } + } + + // part 2: from cm to c1 + if (carea.get_width() > 0) { + for (gint i = 0; i < 4; i++) { + c[i] = _cm[i] << 16; + dc[i] = ((_c1[i] << 16) - c[i]) / (carea.get_width() / 2); + } + guint wi = carea.get_width() / 2; + const guchar *b = sp_color_slider_render_gradient(carea.get_width() / 2, 0, wi, carea.get_height(), c, dc, + _b0, _b1, _bmask); + + /* Draw pixelstore 2 */ + if (b != NULL && wi > 0) { + Glib::RefPtr<Gdk::Pixbuf> pb = + Gdk::Pixbuf::create_from_data(b, Gdk::COLORSPACE_RGB, false, 8, wi, carea.get_height(), wi * 3); + + Gdk::Cairo::set_source_pixbuf(cr, pb, carea.get_width() / 2 + carea.get_x(), carea.get_y()); + cr->paint(); + } + } + } + + /* Draw shadow */ + if (!colorsOnTop) { +#if GTK_CHECK_VERSION(3, 0, 0) + style_context->render_frame(cr, 0, 0, allocation.get_width(), allocation.get_height()); +#else + gtk_paint_shadow(style->gobj(), window->gobj(), gtk_widget_get_state(gobj()), GTK_SHADOW_IN, NULL, gobj(), + "colorslider", 0, 0, allocation.get_width(), allocation.get_height()); +#endif + } + + /* Draw arrow */ + gint x = (int)(_value * (carea.get_width() - 1) - ARROW_SIZE / 2 + carea.get_x()); + gint y1 = carea.get_y(); + gint y2 = carea.get_y() + carea.get_height() - 1; + cr->set_line_width(1.0); + + // Define top arrow + cr->move_to(x - 0.5, y1 + 0.5); + cr->line_to(x + ARROW_SIZE - 0.5, y1 + 0.5); + cr->line_to(x + (ARROW_SIZE - 1) / 2.0, y1 + ARROW_SIZE / 2.0 + 0.5); + cr->line_to(x - 0.5, y1 + 0.5); + + // Define bottom arrow + cr->move_to(x - 0.5, y2 + 0.5); + cr->line_to(x + ARROW_SIZE - 0.5, y2 + 0.5); + cr->line_to(x + (ARROW_SIZE - 1) / 2.0, y2 - ARROW_SIZE / 2.0 + 0.5); + cr->line_to(x - 0.5, y2 + 0.5); + + // Render both arrows + cr->set_source_rgb(1.0, 1.0, 1.0); + cr->stroke_preserve(); + cr->set_source_rgb(0.0, 0.0, 0.0); + cr->fill(); + + return false; +} + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* Colors are << 16 */ + +static const guchar *sp_color_slider_render_gradient(gint x0, gint y0, gint width, gint height, gint c[], gint dc[], + guint b0, guint b1, guint mask) +{ + static guchar *buf = NULL; + static gint bs = 0; + guchar *dp; + gint x, y; + guint r, g, b, a; + + if (buf && (bs < width * height)) { + g_free(buf); + buf = NULL; + } + if (!buf) { + buf = g_new(guchar, width * height * 3); + bs = width * height; + } + + dp = buf; + r = c[0]; + g = c[1]; + b = c[2]; + a = c[3]; + for (x = x0; x < x0 + width; x++) { + gint cr, cg, cb, ca; + guchar *d; + cr = r >> 16; + cg = g >> 16; + cb = b >> 16; + ca = a >> 16; + d = dp; + for (y = y0; y < y0 + height; y++) { + guint bg, fc; + /* Background value */ + bg = ((x & mask) ^ (y & mask)) ? b0 : b1; + fc = (cr - bg) * ca; + d[0] = bg + ((fc + (fc >> 8) + 0x80) >> 8); + fc = (cg - bg) * ca; + d[1] = bg + ((fc + (fc >> 8) + 0x80) >> 8); + fc = (cb - bg) * ca; + d[2] = bg + ((fc + (fc >> 8) + 0x80) >> 8); + d += 3 * width; + } + r += dc[0]; + g += dc[1]; + b += dc[2]; + a += dc[3]; + dp += 3; + } + + return buf; +} + +/* Positions are << 16 */ + +static const guchar *sp_color_slider_render_map(gint x0, gint y0, gint width, gint height, guchar *map, gint start, + gint step, guint b0, guint b1, guint mask) +{ + static guchar *buf = NULL; + static gint bs = 0; + guchar *dp; + gint x, y; + + if (buf && (bs < width * height)) { + g_free(buf); + buf = NULL; + } + if (!buf) { + buf = g_new(guchar, width * height * 3); + bs = width * height; + } + + dp = buf; + for (x = x0; x < x0 + width; x++) { + gint cr, cg, cb, ca; + guchar *d = dp; + guchar *sp = map + 4 * (start >> 16); + cr = *sp++; + cg = *sp++; + cb = *sp++; + ca = *sp++; + for (y = y0; y < y0 + height; y++) { + guint bg, fc; + /* Background value */ + bg = ((x & mask) ^ (y & mask)) ? b0 : b1; + fc = (cr - bg) * ca; + d[0] = bg + ((fc + (fc >> 8) + 0x80) >> 8); + fc = (cg - bg) * ca; + d[1] = bg + ((fc + (fc >> 8) + 0x80) >> 8); + fc = (cb - bg) * ca; + d[2] = bg + ((fc + (fc >> 8) + 0x80) >> 8); + d += 3 * width; + } + dp += 3; + start += step; + } + + return buf; +} diff --git a/src/ui/widget/color-slider.h b/src/ui/widget/color-slider.h new file mode 100644 index 000000000..253f3123c --- /dev/null +++ b/src/ui/widget/color-slider.h @@ -0,0 +1,110 @@ +/* + * A slider with colored background + * + * Author: + * Lauris Kaplinski <lauris@kaplinski.com> + * + * Copyright (C) 2001-2002 Lauris Kaplinski + * + * This code is in public domain + */ + +#ifndef SEEN_COLOR_SLIDER_H +#define SEEN_COLOR_SLIDER_H + +#include <gtkmm/widget.h> +#include <sigc++/signal.h> + +namespace Inkscape { +namespace UI { +namespace Widget { + +/* + * A slider with colored background + */ +class ColorSlider : public Gtk::Widget { +public: +#if GTK_CHECK_VERSION(3, 0, 0) + ColorSlider(Glib::RefPtr<Gtk::Adjustment> adjustment); +#else + ColorSlider(Gtk::Adjustment *adjustment); +#endif + ~ColorSlider(); + +#if GTK_CHECK_VERSION(3, 0, 0) + void setAdjustment(Glib::RefPtr<Gtk::Adjustment> adjustment); +#else + void setAdjustment(Gtk::Adjustment *adjustment); +#endif + + void setColors(guint32 start, guint32 mid, guint32 end); + + void setMap(const guchar *map); + + void setBackground(guint dark, guint light, guint size); + + sigc::signal<void> signal_grabbed; + sigc::signal<void> signal_dragged; + sigc::signal<void> signal_released; + sigc::signal<void> signal_value_changed; + +protected: + void on_size_allocate(Gtk::Allocation &allocation); + void on_realize(); + void on_unrealize(); + bool on_button_press_event(GdkEventButton *event); + bool on_button_release_event(GdkEventButton *event); + bool on_motion_notify_event(GdkEventMotion *event); + bool on_draw(const Cairo::RefPtr<Cairo::Context> &cr); + +#if GTK_CHECK_VERSION(3, 0, 0) + void get_preferred_width_vfunc(int &minimum_width, int &natural_width) const; + void get_preferred_width_for_height_vfunc(int height, int &minimum_width, int &natural_width) const; + void get_preferred_height_vfunc(int &minimum_height, int &natural_height) const; + void get_preferred_height_for_width_vfunc(int width, int &minimum_height, int &natural_height) const; +#else + void on_size_request(Gtk::Requisition *requisition); + bool on_expose_event(GdkEventExpose *event); +#endif + +private: + void _onAdjustmentChanged(); + void _onAdjustmentValueChanged(); + + bool _dragging; + +#if GTK_CHECK_VERSION(3, 0, 0) + Glib::RefPtr<Gtk::Adjustment> _adjustment; +#else + Gtk::Adjustment *_adjustment; +#endif + sigc::connection _adjustment_changed_connection; + sigc::connection _adjustment_value_changed_connection; + + gfloat _value; + gfloat _oldvalue; + guchar _c0[4], _cm[4], _c1[4]; + guchar _b0, _b1; + guchar _bmask; + + gint _mapsize; + guchar *_map; + + Glib::RefPtr<Gdk::Window> _gdk_window; +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif +/* + 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 : diff --git a/src/ui/widget/color-wheel-selector.cpp b/src/ui/widget/color-wheel-selector.cpp new file mode 100644 index 000000000..ed3400bb5 --- /dev/null +++ b/src/ui/widget/color-wheel-selector.cpp @@ -0,0 +1,302 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "color-wheel-selector.h" + +#include <math.h> +#include <gtk/gtk.h> +#include <glibmm/i18n.h> +#include <gtkmm/adjustment.h> +#include <gtkmm/label.h> +#include <gtkmm/spinbutton.h> +#include "svg/svg-icc-color.h" +#include "ui/dialog-events.h" +#include "ui/selected-color.h" +#include "ui/widget/color-scales.h" +#include "ui/widget/color-slider.h" +#include "ui/widget/gimpcolorwheel.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + + +#define XPAD 4 +#define YPAD 1 + + +const gchar *ColorWheelSelector::MODE_NAME = N_("Wheel"); + +ColorWheelSelector::ColorWheelSelector(SelectedColor &color) +#if GTK_CHECK_VERSION(3, 0, 0) + : Gtk::Grid() +#else + : Gtk::Table(5, 3, false) +#endif + , _color(color) + , _updating(false) +#if !GTK_CHECK_VERSION(3, 0, 0) + , _alpha_adjustment(NULL) +#endif + , _wheel(0) + , _slider(0) +{ + _initUI(); + _color_changed_connection = color.signal_changed.connect(sigc::mem_fun(this, &ColorWheelSelector::_colorChanged)); + _color_dragged_connection = color.signal_dragged.connect(sigc::mem_fun(this, &ColorWheelSelector::_colorChanged)); +} + +ColorWheelSelector::~ColorWheelSelector() +{ + _wheel = 0; +#if !GTK_CHECK_VERSION(3, 0, 0) + delete _alpha_adjustment; +#endif + + _color_changed_connection.disconnect(); + _color_dragged_connection.disconnect(); +} + +void ColorWheelSelector::_initUI() +{ + /* Create components */ + gint row = 0; + + _wheel = gimp_color_wheel_new(); + gtk_widget_show(_wheel); + +#if GTK_CHECK_VERSION(3, 0, 0) + gtk_widget_set_halign(_wheel, GTK_ALIGN_FILL); + gtk_widget_set_valign(_wheel, GTK_ALIGN_FILL); + gtk_widget_set_hexpand(_wheel, TRUE); + gtk_widget_set_vexpand(_wheel, TRUE); + gtk_grid_attach(GTK_GRID(gobj()), _wheel, 0, row, 3, 1); +#else + gtk_table_attach(GTK_TABLE(gobj()), _wheel, 0, 3, row, row + 1, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), + (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), 0, 0); +#endif + + row++; + + /* Label */ + Gtk::Label *label = Gtk::manage(new Gtk::Label(_("_A:"), true)); + label->set_alignment(1.0, 0.5); + label->show(); + +#if GTK_CHECK_VERSION(3, 0, 0) + #if GTK_CHECK_VERSION(3, 12, 0) + label->set_margin_start(XPAD); + label->set_margin_end(XPAD); + #else + label->set_margin_left(XPAD); + label->set_margin_right(XPAD); + #endif + label->set_margin_top(YPAD); + label->set_margin_bottom(YPAD); + label->set_halign(Gtk::ALIGN_FILL); + label->set_valign(Gtk::ALIGN_FILL); + attach(*label, 0, row, 1, 1); +#else + attach(*label, 0, 1, row, row + 1, Gtk::FILL, Gtk::FILL, XPAD, YPAD); +#endif + +/* Adjustment */ +#if GTK_CHECK_VERSION(3, 0, 0) + _alpha_adjustment = Gtk::Adjustment::create(0.0, 0.0, 255.0, 1.0, 10.0, 10.0); +#else + _alpha_adjustment = new Gtk::Adjustment(0.0, 0.0, 255.0, 1.0, 10.0, 10.0); +#endif + /* Slider */ + _slider = Gtk::manage(new Inkscape::UI::Widget::ColorSlider(_alpha_adjustment)); + _slider->set_tooltip_text(_("Alpha (opacity)")); + _slider->show(); + +#if GTK_CHECK_VERSION(3, 0, 0) + #if GTK_CHECK_VERSION(3, 12, 0) + _slider->set_margin_start(XPAD); + _slider->set_margin_end(XPAD); + #else + _slider->set_margin_left(XPAD); + _slider->set_margin_right(XPAD); + #endif + _slider->set_margin_top(YPAD); + _slider->set_margin_bottom(YPAD); + _slider->set_hexpand(true); + _slider->set_halign(Gtk::ALIGN_FILL); + _slider->set_valign(Gtk::ALIGN_FILL); + attach(*_slider, 1, row, 1, 1); +#else + attach(*_slider, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::FILL, XPAD, YPAD); +#endif + + _slider->setColors(SP_RGBA32_F_COMPOSE(1.0, 1.0, 1.0, 0.0), SP_RGBA32_F_COMPOSE(1.0, 1.0, 1.0, 0.5), + SP_RGBA32_F_COMPOSE(1.0, 1.0, 1.0, 1.0)); + +/* Spinbutton */ +#if GTK_CHECK_VERSION(3, 0, 0) + Gtk::SpinButton *spin_button = Gtk::manage(new Gtk::SpinButton(_alpha_adjustment, 1.0, 0)); +#else + Gtk::SpinButton *spin_button = Gtk::manage(new Gtk::SpinButton(*_alpha_adjustment, 1.0, 0)); +#endif + spin_button->set_tooltip_text(_("Alpha (opacity)")); + sp_dialog_defocus_on_enter(GTK_WIDGET(spin_button->gobj())); + label->set_mnemonic_widget(*spin_button); + spin_button->show(); + +#if GTK_CHECK_VERSION(3, 0, 0) + #if GTK_CHECK_VERSION(3, 12, 0) + spin_button->set_margin_start(XPAD); + spin_button->set_margin_end(XPAD); + #else + spin_button->set_margin_left(XPAD); + spin_button->set_margin_right(XPAD); + #endif + spin_button->set_margin_top(YPAD); + spin_button->set_margin_bottom(YPAD); + spin_button->set_halign(Gtk::ALIGN_CENTER); + spin_button->set_valign(Gtk::ALIGN_CENTER); + attach(*spin_button, 2, row, 1, 1); +#else + attach(*spin_button, 2, 3, row, row + 1, (Gtk::AttachOptions)0, (Gtk::AttachOptions)0, XPAD, YPAD); +#endif + + /* Signals */ + _alpha_adjustment->signal_value_changed().connect(sigc::mem_fun(this, &ColorWheelSelector::_adjustmentChanged)); + _slider->signal_grabbed.connect(sigc::mem_fun(*this, &ColorWheelSelector::_sliderGrabbed)); + _slider->signal_released.connect(sigc::mem_fun(*this, &ColorWheelSelector::_sliderReleased)); + _slider->signal_value_changed.connect(sigc::mem_fun(*this, &ColorWheelSelector::_sliderChanged)); + + g_signal_connect(G_OBJECT(_wheel), "changed", G_CALLBACK(_wheelChanged), this); +} + +void ColorWheelSelector::on_show() +{ +#if GTK_CHECK_VERSION(3, 0, 0) + Gtk::Grid::on_show(); +#else + Gtk::Table::on_show(); +#endif + _updateDisplay(); +} + +void ColorWheelSelector::_colorChanged() +{ + _updateDisplay(); +} + +void ColorWheelSelector::_adjustmentChanged() +{ + if (_updating) { + return; + } + + // TODO check this. It looks questionable: + // if a value is entered between 0 and 1 exclusive, normalize it to (int) 0..255 or 0..100 + gdouble value = _alpha_adjustment->get_value(); + gdouble upper = _alpha_adjustment->get_upper(); + if (value > 0.0 && value < 1.0) { + _alpha_adjustment->set_value(floor(value * upper + 0.5)); + } + + _color.preserveICC(); + _color.setAlpha(ColorScales::getScaled(_alpha_adjustment->gobj())); +} + +void ColorWheelSelector::_sliderGrabbed() +{ + _color.preserveICC(); + _color.setHeld(true); +} + +void ColorWheelSelector::_sliderReleased() +{ + _color.preserveICC(); + _color.setHeld(false); +} + +void ColorWheelSelector::_sliderChanged() +{ + if (_updating) { + return; + } + + _color.preserveICC(); + _color.setAlpha(ColorScales::getScaled(_alpha_adjustment->gobj())); +} + +void ColorWheelSelector::_wheelChanged(GimpColorWheel *wheel, ColorWheelSelector *wheelSelector) +{ + if (wheelSelector->_updating) { + return; + } + + gdouble h = 0; + gdouble s = 0; + gdouble v = 0; + gimp_color_wheel_get_color(wheel, &h, &s, &v); + + float rgb[3] = { 0, 0, 0 }; + sp_color_hsv_to_rgb_floatv(rgb, h, s, v); + + SPColor color(rgb[0], rgb[1], rgb[2]); + + guint32 start = color.toRGBA32(0x00); + guint32 mid = color.toRGBA32(0x7f); + guint32 end = color.toRGBA32(0xff); + + wheelSelector->_slider->setColors(start, mid, end); + + wheelSelector->_color.preserveICC(); + + wheelSelector->_color.setHeld(gimp_color_wheel_is_adjusting(wheel)); + wheelSelector->_color.setColor(color); +} + +void ColorWheelSelector::_updateDisplay() +{ +#ifdef DUMP_CHANGE_INFO + g_message("ColorWheelSelector::_colorChanged( this=%p, %f, %f, %f, %f)", this, _color.color().v.c[0], + _color.color().v.c[1], _color.color().v.c[2], alpha); +#endif + + bool oldval = _updating; + _updating = true; + { + float hsv[3] = { 0, 0, 0 }; + sp_color_rgb_to_hsv_floatv(hsv, _color.color().v.c[0], _color.color().v.c[1], _color.color().v.c[2]); + gimp_color_wheel_set_color(GIMP_COLOR_WHEEL(_wheel), hsv[0], hsv[1], hsv[2]); + } + + guint32 start = _color.color().toRGBA32(0x00); + guint32 mid = _color.color().toRGBA32(0x7f); + guint32 end = _color.color().toRGBA32(0xff); + + _slider->setColors(start, mid, end); + + ColorScales::setScaled(_alpha_adjustment->gobj(), _color.alpha()); + + _updating = oldval; +} + + +Gtk::Widget *ColorWheelSelectorFactory::createWidget(Inkscape::UI::SelectedColor &color) const +{ + Gtk::Widget *w = Gtk::manage(new ColorWheelSelector(color)); + return w; +} + +Glib::ustring ColorWheelSelectorFactory::modeName() const { return gettext(ColorWheelSelector::MODE_NAME); } +} +} +} +/* + 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 : diff --git a/src/ui/widget/color-wheel-selector.h b/src/ui/widget/color-wheel-selector.h new file mode 100644 index 000000000..5711d417c --- /dev/null +++ b/src/ui/widget/color-wheel-selector.h @@ -0,0 +1,101 @@ +/** + * @file + * Color selector widget containing GIMP color wheel and slider + */ +/* Authors: + * Tomasz Boczkowski <penginsbacon@gmail.com> (c++-sification) + * + * Copyright (C) 2014 Authors + * + * This code is in public domain + */ +#ifndef SEEN_SP_COLOR_WHEEL_SELECTOR_H +#define SEEN_SP_COLOR_WHEEL_SELECTOR_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#if WITH_GTKMM_3_0 +#include <gtkmm/grid.h> +#else +#include <gtkmm/table.h> +#endif + +#include "ui/selected-color.h" + +typedef struct _GimpColorWheel GimpColorWheel; + +namespace Inkscape { +namespace UI { +namespace Widget { + +class ColorSlider; + +class ColorWheelSelector +#if GTK_CHECK_VERSION(3, 0, 0) + : public Gtk::Grid +#else + : public Gtk::Table +#endif +{ +public: + static const gchar *MODE_NAME; + + ColorWheelSelector(SelectedColor &color); + virtual ~ColorWheelSelector(); + +protected: + void _initUI(); + + void on_show(); + + void _colorChanged(); + void _adjustmentChanged(); + void _sliderGrabbed(); + void _sliderReleased(); + void _sliderChanged(); + static void _wheelChanged(GimpColorWheel *wheel, ColorWheelSelector *cs); + + void _updateDisplay(); + + SelectedColor &_color; + bool _updating; +#if GTK_CHECK_VERSION(3, 0, 0) + Glib::RefPtr<Gtk::Adjustment> _alpha_adjustment; +#else + Gtk::Adjustment *_alpha_adjustment; +#endif + GtkWidget *_wheel; + Inkscape::UI::Widget::ColorSlider *_slider; + +private: + // By default, disallow copy constructor and assignment operator + ColorWheelSelector(const ColorWheelSelector &obj); + ColorWheelSelector &operator=(const ColorWheelSelector &obj); + + sigc::connection _color_changed_connection; + sigc::connection _color_dragged_connection; +}; + +class ColorWheelSelectorFactory : public ColorSelectorFactory { +public: + Gtk::Widget *createWidget(SelectedColor &color) const; + Glib::ustring modeName() const; +}; +} +} +} + +#endif // SEEN_SP_COLOR_WHEEL_SELECTOR_H + +/* + 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 : diff --git a/src/ui/widget/font-variants.cpp b/src/ui/widget/font-variants.cpp new file mode 100644 index 000000000..637631fda --- /dev/null +++ b/src/ui/widget/font-variants.cpp @@ -0,0 +1,512 @@ +/* + * Author: + * Tavmjong Bah <tavmjong@free.fr> + * + * Copyright (C) 2015 Tavmong Bah + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <gtkmm.h> +#include <glibmm/i18n.h> + +#include <iostream> + +#include "font-variants.h" + +// For updating from selection +#include "desktop.h" +#include "selection.h" +#include "style.h" +#include "sp-text.h" +#include "sp-tspan.h" +#include "sp-tref.h" +#include "sp-textpath.h" +#include "sp-item-group.h" +#include "xml/repr.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + + FontVariants::FontVariants () : + Gtk::VBox (), + _ligatures_frame ( Glib::ustring(_("Ligatures" )) ), + _ligatures_common ( Glib::ustring(_("Common" )) ), + _ligatures_discretionary ( Glib::ustring(_("Discretionary")) ), + _ligatures_historical ( Glib::ustring(_("Historical" )) ), + _ligatures_contextual ( Glib::ustring(_("Contextual" )) ), + + _position_frame ( Glib::ustring(_("Position" )) ), + _position_normal ( Glib::ustring(_("Normal" )) ), + _position_sub ( Glib::ustring(_("Subscript" )) ), + _position_super ( Glib::ustring(_("Superscript" )) ), + + _caps_frame ( Glib::ustring(_("Capitals" )) ), + _caps_normal ( Glib::ustring(_("Normal" )) ), + _caps_small ( Glib::ustring(_("Small" )) ), + _caps_all_small ( Glib::ustring(_("All small" )) ), + _caps_petite ( Glib::ustring(_("Petite" )) ), + _caps_all_petite ( Glib::ustring(_("All petite" )) ), + _caps_unicase ( Glib::ustring(_("Unicase" )) ), + _caps_titling ( Glib::ustring(_("Titling" )) ), + + _numeric_frame ( Glib::ustring(_("Numeric" )) ), + _numeric_lining ( Glib::ustring(_("Lining" )) ), + _numeric_old_style ( Glib::ustring(_("Old Style" )) ), + _numeric_default_style ( Glib::ustring(_("Default Style")) ), + _numeric_proportional ( Glib::ustring(_("Proportional" )) ), + _numeric_tabular ( Glib::ustring(_("Tabular" )) ), + _numeric_default_width ( Glib::ustring(_("Default Width")) ), + _numeric_diagonal ( Glib::ustring(_("Diagonal" )) ), + _numeric_stacked ( Glib::ustring(_("Stacked" )) ), + _numeric_default_fractions( Glib::ustring(_("Default Fractions")) ), + _numeric_ordinal ( Glib::ustring(_("Ordinal" )) ), + _numeric_slashed_zero ( Glib::ustring(_("Slashed Zero" )) ), + + _ligatures_changed( false ), + _position_changed( false ), + _caps_changed( false ), + _numeric_changed( false ) + + { + + // Ligatures -------------------------- + + // Add tooltips + _ligatures_common.set_tooltip_text( + _("Common ligatures. On by default. OpenType tables: 'liga', 'clig'")); + _ligatures_discretionary.set_tooltip_text( + _("Discretionary ligatures. Off by default. OpenType table: 'dlig'")); + _ligatures_historical.set_tooltip_text( + _("Historical ligatures. Off by default. OpenType table: 'hlig'")); + _ligatures_contextual.set_tooltip_text( + _("Contextual forms. On by default. OpenType table: 'calt'")); + + // Add signals + _ligatures_common.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::ligatures_callback) ); + _ligatures_discretionary.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::ligatures_callback) ); + _ligatures_historical.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::ligatures_callback) ); + _ligatures_contextual.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::ligatures_callback) ); + + // Add to frame + _ligatures_vbox.add( _ligatures_common ); + _ligatures_vbox.add( _ligatures_discretionary ); + _ligatures_vbox.add( _ligatures_historical ); + _ligatures_vbox.add( _ligatures_contextual ); + _ligatures_frame.add( _ligatures_vbox ); + add( _ligatures_frame ); + + ligatures_init(); + + // Position ---------------------------------- + + // Add tooltips + _position_normal.set_tooltip_text( _("Normal position.")); + _position_sub.set_tooltip_text( _("Subscript. OpenType table: 'subs'") ); + _position_super.set_tooltip_text( _("Superscript. OpenType table: 'sups'") ); + + // Group buttons + Gtk::RadioButton::Group position_group = _position_normal.get_group(); + _position_sub.set_group(position_group); + _position_super.set_group(position_group); + + // Add signals + _position_normal.signal_pressed().connect ( sigc::mem_fun(*this, &FontVariants::position_callback) ); + _position_sub.signal_pressed().connect ( sigc::mem_fun(*this, &FontVariants::position_callback) ); + _position_super.signal_pressed().connect ( sigc::mem_fun(*this, &FontVariants::position_callback) ); + + // Add to frame + _position_vbox.add( _position_normal ); + _position_vbox.add( _position_sub ); + _position_vbox.add( _position_super ); + _position_frame.add( _position_vbox ); + add( _position_frame ); + + position_init(); + + // Caps ---------------------------------- + + // Add tooltips + _caps_normal.set_tooltip_text( _("Normal capitalization.")); + _caps_small.set_tooltip_text( _("Small-caps (lowercase). OpenType table: 'smcp'")); + _caps_all_small.set_tooltip_text( _("All small-caps (uppercase and lowercase). OpenType tables: 'c2sc' and 'smcp'")); + _caps_petite.set_tooltip_text( _("Petite-caps (lowercase). OpenType table: 'pcap'")); + _caps_all_petite.set_tooltip_text( _("All petite-caps (uppercase and lowercase). OpenType tables: 'c2sc' and 'pcap'")); + _caps_unicase.set_tooltip_text( _("Unicase (small caps for uppercase, normal for lowercase). OpenType table: 'unic'")); + _caps_titling.set_tooltip_text( _("Titling caps (lighter-weight uppercase for use in titles). OpenType table: 'titl'")); + + // Group buttons + Gtk::RadioButton::Group caps_group = _caps_normal.get_group(); + _caps_small.set_group(caps_group); + _caps_all_small.set_group(caps_group); + _caps_petite.set_group(caps_group); + _caps_all_petite.set_group(caps_group); + _caps_unicase.set_group(caps_group); + _caps_titling.set_group(caps_group); + + // Add signals + _caps_normal.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::caps_callback) ); + _caps_small.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::caps_callback) ); + _caps_all_small.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::caps_callback) ); + _caps_petite.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::caps_callback) ); + _caps_all_petite.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::caps_callback) ); + _caps_unicase.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::caps_callback) ); + _caps_titling.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::caps_callback) ); + + // Add to frame + _caps_vbox.add( _caps_normal ); + _caps_vbox.add( _caps_small ); + _caps_vbox.add( _caps_all_small ); + _caps_vbox.add( _caps_petite ); + _caps_vbox.add( _caps_all_petite ); + _caps_vbox.add( _caps_unicase ); + _caps_vbox.add( _caps_titling ); + _caps_frame.add( _caps_vbox ); + add( _caps_frame ); + + caps_init(); + + // Numeric ------------------------------ + + // Add tooltips + _numeric_default_style.set_tooltip_text( _("Normal style.")); + _numeric_lining.set_tooltip_text( _("Lining numerals. OpenType table: 'lnum'")); + _numeric_old_style.set_tooltip_text( _("Old style numerals. OpenType table: 'onum'")); + _numeric_default_width.set_tooltip_text( _("Normal widths.")); + _numeric_proportional.set_tooltip_text( _("Proportional width numerals. OpenType table: 'pnum'")); + _numeric_tabular.set_tooltip_text( _("Same width numerals. OpenType table: 'tnum'")); + _numeric_default_fractions.set_tooltip_text( _("Normal fractions.")); + _numeric_diagonal.set_tooltip_text( _("Diagonal fractions. OpenType table: 'frac'")); + _numeric_stacked.set_tooltip_text( _("Stacked fractions. OpenType table: 'afrc'")); + _numeric_ordinal.set_tooltip_text( _("Ordinals (raised 'th', etc.). OpenType table: 'ordn'")); + _numeric_slashed_zero.set_tooltip_text( _("Slashed zeros. OpenType table: 'zero'")); + + // Group buttons + Gtk::RadioButton::Group style_group = _numeric_default_style.get_group(); + _numeric_lining.set_group(style_group); + _numeric_old_style.set_group(style_group); + + Gtk::RadioButton::Group width_group = _numeric_default_width.get_group(); + _numeric_proportional.set_group(width_group); + _numeric_tabular.set_group(width_group); + + Gtk::RadioButton::Group fraction_group = _numeric_default_fractions.get_group(); + _numeric_diagonal.set_group(fraction_group); + _numeric_stacked.set_group(fraction_group); + + // Add signals + _numeric_default_style.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) ); + _numeric_lining.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) ); + _numeric_old_style.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) ); + _numeric_default_width.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) ); + _numeric_proportional.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) ); + _numeric_tabular.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) ); + _numeric_default_fractions.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) ); + _numeric_diagonal.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) ); + _numeric_stacked.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) ); + _numeric_ordinal.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) ); + _numeric_slashed_zero.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::numeric_callback) ); + + // Add to frame + _numeric_stylebox.add( _numeric_default_style ); + _numeric_stylebox.add( _numeric_lining ); + _numeric_stylebox.add( _numeric_old_style ); + _numeric_vbox.add( _numeric_stylebox ); + _numeric_widthbox.add( _numeric_default_width ); + _numeric_widthbox.add( _numeric_proportional ); + _numeric_widthbox.add( _numeric_tabular ); + _numeric_vbox.add( _numeric_widthbox ); + _numeric_fractionbox.add( _numeric_default_fractions ); + _numeric_fractionbox.add( _numeric_diagonal ); + _numeric_fractionbox.add( _numeric_stacked ); + _numeric_vbox.add( _numeric_fractionbox ); + _numeric_vbox.add( _numeric_ordinal ); + _numeric_vbox.add( _numeric_slashed_zero ); + _numeric_frame.add( _numeric_vbox ); + add( _numeric_frame ); + + + show_all_children(); + + } + + void + FontVariants::ligatures_init() { + // std::cout << "FontVariants::ligatures_init()" << std::endl; + } + + void + FontVariants::ligatures_callback() { + // std::cout << "FontVariants::ligatures_callback()" << std::endl; + _ligatures_changed = true; + _changed_signal.emit(); + } + + void + FontVariants::position_init() { + // std::cout << "FontVariants::position_init()" << std::endl; + } + + void + FontVariants::position_callback() { + // std::cout << "FontVariants::position_callback()" << std::endl; + _position_changed = true; + _changed_signal.emit(); + } + + void + FontVariants::caps_init() { + // std::cout << "FontVariants::caps_init()" << std::endl; + } + + void + FontVariants::caps_callback() { + // std::cout << "FontVariants::caps_callback()" << std::endl; + _caps_changed = true; + _changed_signal.emit(); + } + + void + FontVariants::numeric_init() { + // std::cout << "FontVariants::numeric_init()" << std::endl; + } + + void + FontVariants::numeric_callback() { + // std::cout << "FontVariants::numeric_callback()" << std::endl; + _numeric_changed = true; + _changed_signal.emit(); + } + + // Update GUI based on query. + void + FontVariants::update( SPStyle const *query ) { + + _ligatures_all = query->font_variant_ligatures.computed; + _ligatures_mix = query->font_variant_ligatures.value; + + _ligatures_common.set_active( _ligatures_all & SP_CSS_FONT_VARIANT_LIGATURES_COMMON ); + _ligatures_discretionary.set_active(_ligatures_all & SP_CSS_FONT_VARIANT_LIGATURES_DISCRETIONARY ); + _ligatures_historical.set_active( _ligatures_all & SP_CSS_FONT_VARIANT_LIGATURES_HISTORICAL ); + _ligatures_contextual.set_active( _ligatures_all & SP_CSS_FONT_VARIANT_LIGATURES_CONTEXTUAL ); + + _ligatures_common.set_inconsistent( _ligatures_mix & SP_CSS_FONT_VARIANT_LIGATURES_COMMON ); + _ligatures_discretionary.set_inconsistent( _ligatures_mix & SP_CSS_FONT_VARIANT_LIGATURES_DISCRETIONARY ); + _ligatures_historical.set_inconsistent( _ligatures_mix & SP_CSS_FONT_VARIANT_LIGATURES_HISTORICAL ); + _ligatures_contextual.set_inconsistent( _ligatures_mix & SP_CSS_FONT_VARIANT_LIGATURES_CONTEXTUAL ); + + _position_all = query->font_variant_position.computed; + _position_mix = query->font_variant_position.value; + + _position_normal.set_active( _position_all & SP_CSS_FONT_VARIANT_POSITION_NORMAL ); + _position_sub.set_active( _position_all & SP_CSS_FONT_VARIANT_POSITION_SUB ); + _position_super.set_active( _position_all & SP_CSS_FONT_VARIANT_POSITION_SUPER ); + + _position_normal.set_inconsistent( _position_mix & SP_CSS_FONT_VARIANT_POSITION_NORMAL ); + _position_sub.set_inconsistent( _position_mix & SP_CSS_FONT_VARIANT_POSITION_SUB ); + _position_super.set_inconsistent( _position_mix & SP_CSS_FONT_VARIANT_POSITION_SUPER ); + + _caps_all = query->font_variant_caps.computed; + _caps_mix = query->font_variant_caps.value; + + _caps_normal.set_active( _caps_all & SP_CSS_FONT_VARIANT_CAPS_NORMAL ); + _caps_small.set_active( _caps_all & SP_CSS_FONT_VARIANT_CAPS_SMALL ); + _caps_all_small.set_active( _caps_all & SP_CSS_FONT_VARIANT_CAPS_ALL_SMALL ); + _caps_petite.set_active( _caps_all & SP_CSS_FONT_VARIANT_CAPS_PETITE ); + _caps_all_petite.set_active( _caps_all & SP_CSS_FONT_VARIANT_CAPS_ALL_PETITE ); + _caps_unicase.set_active( _caps_all & SP_CSS_FONT_VARIANT_CAPS_UNICASE ); + _caps_titling.set_active( _caps_all & SP_CSS_FONT_VARIANT_CAPS_TITLING ); + + _caps_normal.set_inconsistent( _caps_mix & SP_CSS_FONT_VARIANT_CAPS_NORMAL ); + _caps_small.set_inconsistent( _caps_mix & SP_CSS_FONT_VARIANT_CAPS_SMALL ); + _caps_all_small.set_inconsistent( _caps_mix & SP_CSS_FONT_VARIANT_CAPS_ALL_SMALL ); + _caps_petite.set_inconsistent( _caps_mix & SP_CSS_FONT_VARIANT_CAPS_PETITE ); + _caps_all_petite.set_inconsistent( _caps_mix & SP_CSS_FONT_VARIANT_CAPS_ALL_PETITE ); + _caps_unicase.set_inconsistent( _caps_mix & SP_CSS_FONT_VARIANT_CAPS_UNICASE ); + _caps_titling.set_inconsistent( _caps_mix & SP_CSS_FONT_VARIANT_CAPS_TITLING ); + + _numeric_all = query->font_variant_numeric.computed; + _numeric_mix = query->font_variant_numeric.value; + + if (_numeric_all & SP_CSS_FONT_VARIANT_NUMERIC_LINING_NUMS) { + _numeric_lining.set_active(); + } else if (_numeric_all & SP_CSS_FONT_VARIANT_NUMERIC_OLDSTYLE_NUMS) { + _numeric_old_style.set_active(); + } else { + _numeric_default_style.set_active(); + } + + if (_numeric_all & SP_CSS_FONT_VARIANT_NUMERIC_PROPORTIONAL_NUMS) { + _numeric_proportional.set_active(); + } else if (_numeric_all & SP_CSS_FONT_VARIANT_NUMERIC_TABULAR_NUMS) { + _numeric_tabular.set_active(); + } else { + _numeric_default_width.set_active(); + } + + if (_numeric_all & SP_CSS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS) { + _numeric_diagonal.set_active(); + } else if (_numeric_all & SP_CSS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS) { + _numeric_stacked.set_active(); + } else { + _numeric_default_fractions.set_active(); + } + + _numeric_ordinal.set_active( _numeric_all & SP_CSS_FONT_VARIANT_NUMERIC_ORDINAL ); + _numeric_slashed_zero.set_active( _numeric_all & SP_CSS_FONT_VARIANT_NUMERIC_SLASHED_ZERO ); + + + _numeric_lining.set_inconsistent( _numeric_mix & SP_CSS_FONT_VARIANT_NUMERIC_LINING_NUMS ); + _numeric_old_style.set_inconsistent( _numeric_mix & SP_CSS_FONT_VARIANT_NUMERIC_OLDSTYLE_NUMS ); + _numeric_proportional.set_inconsistent( _numeric_mix & SP_CSS_FONT_VARIANT_NUMERIC_PROPORTIONAL_NUMS ); + _numeric_tabular.set_inconsistent( _numeric_mix & SP_CSS_FONT_VARIANT_NUMERIC_TABULAR_NUMS ); + _numeric_diagonal.set_inconsistent( _numeric_mix & SP_CSS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS ); + _numeric_stacked.set_inconsistent( _numeric_mix & SP_CSS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS ); + _numeric_ordinal.set_inconsistent( _numeric_mix & SP_CSS_FONT_VARIANT_NUMERIC_ORDINAL ); + _numeric_slashed_zero.set_inconsistent( _numeric_mix & SP_CSS_FONT_VARIANT_NUMERIC_SLASHED_ZERO ); + + _ligatures_changed = false; + _position_changed = false; + _caps_changed = false; + _numeric_changed = false; + } + + void + FontVariants::fill_css( SPCSSAttr *css ) { + + // Ligatures + bool common = _ligatures_common.get_active(); + bool discretionary = _ligatures_discretionary.get_active(); + bool historical = _ligatures_historical.get_active(); + bool contextual = _ligatures_contextual.get_active(); + + if( !common && !discretionary && !historical && !contextual ) { + sp_repr_css_set_property(css, "font-variant-ligatures", "none" ); + } else if ( common && !discretionary && !historical && contextual ) { + sp_repr_css_set_property(css, "font-variant-ligatures", "normal" ); + } else { + Glib::ustring css_string; + if ( !common ) + css_string += "no-common-ligatures "; + if ( discretionary ) + css_string += "discretionary-ligatures "; + if ( historical ) + css_string += "historical-ligatures "; + if ( !contextual ) + css_string += "no-contextual "; + sp_repr_css_set_property(css, "font-variant-ligatures", css_string.c_str() ); + } + + // Position + { + unsigned position_new = SP_CSS_FONT_VARIANT_POSITION_NORMAL; + Glib::ustring css_string; + if( _position_normal.get_active() ) { + css_string = "normal"; + } else if( _position_sub.get_active() ) { + css_string = "sub"; + position_new = SP_CSS_FONT_VARIANT_POSITION_SUB; + } else if( _position_super.get_active() ) { + css_string = "super"; + position_new = SP_CSS_FONT_VARIANT_POSITION_SUPER; + } + + // 'if' may not be necessary... need to test. + if( (_position_all != position_new) || ((_position_mix != 0) && _position_changed) ) { + sp_repr_css_set_property(css, "font-variant-position", css_string.c_str() ); + } + } + + // Caps + { + unsigned caps_new = SP_CSS_FONT_VARIANT_CAPS_NORMAL; + Glib::ustring css_string; + if( _caps_normal.get_active() ) { + css_string = "normal"; + caps_new = SP_CSS_FONT_VARIANT_CAPS_NORMAL; + } else if( _caps_small.get_active() ) { + css_string = "small-caps"; + caps_new = SP_CSS_FONT_VARIANT_CAPS_SMALL; + } else if( _caps_all_small.get_active() ) { + css_string = "all-small-caps"; + caps_new = SP_CSS_FONT_VARIANT_CAPS_ALL_SMALL; + } else if( _caps_all_petite.get_active() ) { + css_string = "petite"; + caps_new = SP_CSS_FONT_VARIANT_CAPS_PETITE; + } else if( _caps_all_petite.get_active() ) { + css_string = "all-petite"; + caps_new = SP_CSS_FONT_VARIANT_CAPS_ALL_PETITE; + } else if( _caps_unicase.get_active() ) { + css_string = "unicase"; + caps_new = SP_CSS_FONT_VARIANT_CAPS_UNICASE; + } else if( _caps_titling.get_active() ) { + css_string = "titling"; + caps_new = SP_CSS_FONT_VARIANT_CAPS_TITLING; + } + + // May not be necessary... need to test. + //if( (_caps_all != caps_new) || ((_caps_mix != 0) && _caps_changed) ) { + sp_repr_css_set_property(css, "font-variant-caps", css_string.c_str() ); + //} + } + + // Numeric + bool default_style = _numeric_default_style.get_active(); + bool lining = _numeric_lining.get_active(); + bool old_style = _numeric_old_style.get_active(); + + bool default_width = _numeric_default_width.get_active(); + bool proportional = _numeric_proportional.get_active(); + bool tabular = _numeric_tabular.get_active(); + + bool default_fractions = _numeric_default_fractions.get_active(); + bool diagonal = _numeric_diagonal.get_active(); + bool stacked = _numeric_stacked.get_active(); + + bool ordinal = _numeric_ordinal.get_active(); + bool slashed_zero = _numeric_slashed_zero.get_active(); + + if (default_style & default_width & default_fractions & !ordinal & !slashed_zero) { + sp_repr_css_set_property(css, "font-variant-numeric", "normal"); + } else { + Glib::ustring css_string; + if ( lining ) + css_string += "lining-nums "; + if ( old_style ) + css_string += "oldstyle-nums "; + if ( proportional ) + css_string += "proportional-nums "; + if ( tabular ) + css_string += "tabular-nums "; + if ( diagonal ) + css_string += "diagonal-fractions "; + if ( stacked ) + css_string += "stacked-fractions "; + if ( ordinal ) + css_string += "ordinal "; + if ( slashed_zero ) + css_string += "slashed-zero "; + sp_repr_css_set_property(css, "font-variant-numeric", css_string.c_str() ); + } + + } + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/font-variants.h b/src/ui/widget/font-variants.h new file mode 100644 index 000000000..e6a9dd68b --- /dev/null +++ b/src/ui/widget/font-variants.h @@ -0,0 +1,152 @@ +/* + * Author: + * Tavmjong Bah <tavmjong@free.fr> + * + * Copyright (C) 2015 Tavmong Bah + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_WIDGET_FONT_VARIANT_H +#define INKSCAPE_UI_WIDGET_FONT_VARIANT_H + +#include <gtkmm/expander.h> +#include <gtkmm/checkbutton.h> +#include <gtkmm/radiobutton.h> + +class SPDesktop; +class SPObject; +class SPStyle; +class SPCSSAttr; + +namespace Inkscape { +namespace UI { +namespace Widget { + +/** + * A container for selecting font variants (OpenType Features). + */ +class FontVariants : public Gtk::VBox +{ + +public: + + /** + * Constructor + */ + FontVariants(); + +protected: + // To start, use four check buttons. + Gtk::Expander _ligatures_frame; + Gtk::VBox _ligatures_vbox; + Gtk::CheckButton _ligatures_common; + Gtk::CheckButton _ligatures_discretionary; + Gtk::CheckButton _ligatures_historical; + Gtk::CheckButton _ligatures_contextual; + + // Exclusive options + Gtk::Expander _position_frame; + Gtk::VBox _position_vbox; + Gtk::RadioButton _position_normal; + Gtk::RadioButton _position_sub; + Gtk::RadioButton _position_super; + + // Exclusive options (maybe a dropdown menu to save space?) + Gtk::Expander _caps_frame; + Gtk::VBox _caps_vbox; + Gtk::RadioButton _caps_normal; + Gtk::RadioButton _caps_small; + Gtk::RadioButton _caps_all_small; + Gtk::RadioButton _caps_petite; + Gtk::RadioButton _caps_all_petite; + Gtk::RadioButton _caps_unicase; + Gtk::RadioButton _caps_titling; + + // Complicated! + Gtk::Expander _numeric_frame; + Gtk::VBox _numeric_vbox; + Gtk::HBox _numeric_stylebox; + Gtk::RadioButton _numeric_lining; + Gtk::RadioButton _numeric_old_style; + Gtk::RadioButton _numeric_default_style; + Gtk::HBox _numeric_widthbox; + Gtk::RadioButton _numeric_proportional; + Gtk::RadioButton _numeric_tabular; + Gtk::RadioButton _numeric_default_width; + Gtk::HBox _numeric_fractionbox; + Gtk::RadioButton _numeric_diagonal; + Gtk::RadioButton _numeric_stacked; + Gtk::RadioButton _numeric_default_fractions; + Gtk::CheckButton _numeric_ordinal; + Gtk::CheckButton _numeric_slashed_zero; + +private: + void ligatures_init(); + void ligatures_callback(); + + void position_init(); + void position_callback(); + + void caps_init(); + void caps_callback(); + + void numeric_init(); + void numeric_callback(); + + // To determine if we need to write out property (may not be necessary) + unsigned _ligatures_all; + unsigned _position_all; + unsigned _caps_all; + unsigned _numeric_all; + + unsigned _ligatures_mix; + unsigned _position_mix; + unsigned _caps_mix; + unsigned _numeric_mix; + + bool _ligatures_changed; + bool _position_changed; + bool _caps_changed; + bool _numeric_changed; + + sigc::signal<void> _changed_signal; + +public: + + /** + * Update GUI based on query results. + */ + void update( SPStyle const *query ); + + /** + * Fill SPCSSAttr based on settings of buttons. + */ + void fill_css( SPCSSAttr* css ); + + /** + * Let others know that user has changed GUI settings. + * (Used to enable 'Apply' and 'Default' buttons.) + */ + sigc::connection connectChanged(sigc::slot<void> slot) { + return _changed_signal.connect(slot); + } +}; + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_WIDGET_FONT_VARIANT_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/verbs.cpp b/src/verbs.cpp index ea2c06dcf..e0ef27b0d 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -1350,39 +1350,9 @@ void LayerVerb::perform(SPAction *action, void *data) } case SP_VERB_LAYER_DUPLICATE: { if ( dt->currentLayer() != dt->currentRoot() ) { - // Note with either approach: - // Any clone masters are duplicated, their clones use the *original*, - // but the duplicated master is not linked up as master nor clone of the original. -#if 0 - // Only copies selectable things, honoring locks, visibility, avoids sublayers. - SPObject *new_layer = Inkscape::create_layer(dt->currentRoot(), dt->currentLayer(), LPOS_BELOW); - if ( dt->currentLayer()->label() ) { - gchar* name = g_strdup_printf(_("%s copy"), dt->currentLayer()->label()); - dt->layer_manager->renameLayer( new_layer, name, TRUE ); - g_free(name); - } - sp_edit_select_all(dt); - sp_selection_duplicate(dt, true); - sp_selection_to_prev_layer(dt, true); - dt->setCurrentLayer(new_layer); - sp_edit_select_all(dt); -#else - // Copies everything, regardless of locks, visibility, sublayers. - //XML Tree being directly used here while it shouldn't be. - Inkscape::XML::Node *selected = dt->currentLayer()->getRepr(); - Inkscape::XML::Node *parent = selected->parent(); - Inkscape::XML::Node *dup = selected->duplicate(parent->document()); - parent->addChild(dup, selected); - SPObject *new_layer = dt->currentLayer()->next; - if (new_layer) { - if (new_layer->label()) { - gchar* name = g_strdup_printf(_("%s copy"), new_layer->label()); - dt->layer_manager->renameLayer( new_layer, name, TRUE ); - g_free(name); - } - dt->setCurrentLayer(new_layer); - } -#endif + + sp_selection_duplicate(dt, true, true); + DocumentUndo::done(dt->getDocument(), SP_VERB_LAYER_DUPLICATE, _("Duplicate layer")); diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt index 072b905a2..a3e9e14d0 100644 --- a/src/widgets/CMakeLists.txt +++ b/src/widgets/CMakeLists.txt @@ -41,12 +41,7 @@ set(widgets_SRC select-toolbar.cpp shrink-wrap-button.cpp sp-attribute-widget.cpp - sp-color-icc-selector.cpp - sp-color-notebook.cpp - sp-color-scales.cpp sp-color-selector.cpp - sp-color-slider.cpp - sp-color-wheel-selector.cpp sp-widget.cpp sp-xmlview-attr-list.cpp sp-xmlview-content.cpp @@ -103,12 +98,7 @@ set(widgets_SRC select-toolbar.h shrink-wrap-button.h sp-attribute-widget.h - sp-color-icc-selector.h - sp-color-notebook.h - sp-color-scales.h sp-color-selector.h - sp-color-slider.h - sp-color-wheel-selector.h sp-widget.h sp-xmlview-attr-list.h sp-xmlview-content.h diff --git a/src/widgets/Makefile_insert b/src/widgets/Makefile_insert index dc4c12967..f66be66ed 100644 --- a/src/widgets/Makefile_insert +++ b/src/widgets/Makefile_insert @@ -76,18 +76,8 @@ ink_common_sources += \ widgets/spiral-toolbar.h \ widgets/sp-attribute-widget.cpp \ widgets/sp-attribute-widget.h \ - widgets/sp-color-icc-selector.cpp \ - widgets/sp-color-icc-selector.h \ - widgets/sp-color-notebook.cpp \ - widgets/sp-color-notebook.h \ - widgets/sp-color-scales.cpp \ - widgets/sp-color-scales.h \ widgets/sp-color-selector.cpp \ widgets/sp-color-selector.h \ - widgets/sp-color-slider.cpp \ - widgets/sp-color-slider.h \ - widgets/sp-color-wheel-selector.cpp \ - widgets/sp-color-wheel-selector.h \ widgets/spinbutton-events.cpp \ widgets/spinbutton-events.h \ widgets/sp-widget.cpp \ diff --git a/src/widgets/fill-style.cpp b/src/widgets/fill-style.cpp index b1f812338..fa5eabab4 100644 --- a/src/widgets/fill-style.cpp +++ b/src/widgets/fill-style.cpp @@ -300,7 +300,7 @@ void FillNStroke::performUpdate() psel->setGradientProperties( rg->getUnits(), rg->getSpread() ); } else if (SP_IS_PATTERN(server)) { - SPPattern *pat = pattern_getroot(SP_PATTERN(server)); + SPPattern *pat = SP_PATTERN(server)->rootPattern(); psel->updatePatternList( pat ); } } @@ -431,8 +431,7 @@ void FillNStroke::dragFromPaint() update = true; switch (psel->mode) { - case SPPaintSelector::MODE_COLOR_RGB: - case SPPaintSelector::MODE_COLOR_CMYK: + case SPPaintSelector::MODE_SOLID_COLOR: { // local change, do not update from selection dragId = g_timeout_add_full(G_PRIORITY_DEFAULT, 100, dragDelayCB, this, 0); @@ -505,8 +504,7 @@ void FillNStroke::updateFromPaint() break; } - case SPPaintSelector::MODE_COLOR_RGB: - case SPPaintSelector::MODE_COLOR_CMYK: + case SPPaintSelector::MODE_SOLID_COLOR: { if (kind == FILL) { // FIXME: fix for GTK breakage, see comment in SelectedStyle::on_opacity_changed; here it results in losing release events @@ -656,7 +654,7 @@ void FillNStroke::updateFromPaint() SPPaintServer *server = (kind == FILL) ? selobj->style->getFillPaintServer() : selobj->style->getStrokePaintServer(); - if (SP_IS_PATTERN(server) && pattern_getroot(SP_PATTERN(server)) == pattern) + if (SP_IS_PATTERN(server) && SP_PATTERN(server)->rootPattern() == pattern) // only if this object's pattern is not rooted in our selected pattern, apply continue; } diff --git a/src/widgets/gradient-selector.cpp b/src/widgets/gradient-selector.cpp index 42e59cbfe..402f30846 100644 --- a/src/widgets/gradient-selector.cpp +++ b/src/widgets/gradient-selector.cpp @@ -17,6 +17,10 @@ # include "config.h" #endif +#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H +#include <glibmm/threads.h> +#endif + #include <gtkmm/treeview.h> #include "gradient-vector.h" diff --git a/src/widgets/gradient-vector.cpp b/src/widgets/gradient-vector.cpp index 10d1cc107..259d4c9af 100644 --- a/src/widgets/gradient-vector.cpp +++ b/src/widgets/gradient-vector.cpp @@ -31,17 +31,16 @@ #include "macros.h" #include <glibmm/i18n.h> #include <set> -#include "widgets/gradient-image.h" -#include "inkscape.h" -#include "document-private.h" -#include "gradient-chemistry.h" -#include "helper/window.h" +#include "../widgets/gradient-image.h" +#include "../inkscape.h" +#include "../document-private.h" +#include "../gradient-chemistry.h" +#include "../helper/window.h" #include "io/resource.h" #include "xml/repr.h" -#include "ui/dialog-events.h" -#include "preferences.h" +#include "../preferences.h" #include "svg/css-ostringstream.h" #include "sp-stop.h" #include "selection-chemistry.h" @@ -51,10 +50,16 @@ #include "desktop.h" #include "layer-manager.h" -#include <sigc++/sigc++.h> +#include <sigc++/functors/ptr_fun.h> +#include <sigc++/adaptors/bind.h> #include "document-undo.h" +#include "ui/dialog-events.h" +#include "ui/selected-color.h" +#include "ui/widget/color-notebook.h" + using Inkscape::DocumentUndo; +using Inkscape::UI::SelectedColor; enum { VECTOR_SET, @@ -468,11 +473,10 @@ void SPGradientVectorSelector::setSwatched() ### Vector Editing Widget ##################################################################*/ -#include "widgets/sp-color-notebook.h" #include "widgets/widget-sizes.h" #include "xml/node-event-vector.h" #include "svg/svg-color.h" - +#include "ui/widget/color-notebook.h" #define PAD 4 @@ -491,8 +495,8 @@ static void sp_gradient_vector_widget_destroy(GtkObject *object, gpointer data); static void sp_gradient_vector_gradient_release(SPObject *obj, GtkWidget *widget); static void sp_gradient_vector_gradient_modified(SPObject *obj, guint flags, GtkWidget *widget); -static void sp_gradient_vector_color_dragged(SPColorSelector *csel, GObject *object); -static void sp_gradient_vector_color_changed(SPColorSelector *csel, GObject *object); +static void sp_gradient_vector_color_dragged(Inkscape::UI::SelectedColor *selected_color, GObject *object); +static void sp_gradient_vector_color_changed(Inkscape::UI::SelectedColor *selected_color, GObject *object); static void update_stop_list( GtkWidget *vb, SPGradient *gradient, SPStop *new_stop); static gboolean blocked = FALSE; @@ -649,9 +653,11 @@ static void sp_grad_edit_combo_box_changed (GtkComboBox * /*widget*/, GtkWidget blocked = TRUE; - SPColorSelector *csel = static_cast<SPColorSelector*>(g_object_get_data(G_OBJECT(tbl), "cselector")); + SelectedColor *csel = static_cast<SelectedColor*>(g_object_get_data(G_OBJECT(tbl), "cselector")); // set its color, from the stored array - csel->base->setColorAlpha( stop->getEffectiveColor(), stop->opacity ); + g_object_set_data(G_OBJECT(tbl), "updating_color", reinterpret_cast<void*>(1)); + csel->setColorAlpha(stop->getEffectiveColor(), stop->opacity); + g_object_set_data(G_OBJECT(tbl), "updating_color", reinterpret_cast<void*>(0)); GtkWidget *offspin = GTK_WIDGET(g_object_get_data(G_OBJECT(tbl), "offspn")); GtkWidget *offslide =GTK_WIDGET(g_object_get_data(G_OBJECT(tbl), "offslide")); @@ -832,7 +838,9 @@ static void sp_grd_ed_del_stop(GtkWidget */*widget*/, GtkWidget *vb) static GtkWidget * sp_gradient_vector_widget_new(SPGradient *gradient, SPStop *select_stop) { - GtkWidget *vb, *w, *f, *csel; + using Inkscape::UI::Widget::ColorNotebook; + + GtkWidget *vb, *w, *f; g_return_val_if_fail(!gradient || SP_IS_GRADIENT(gradient), NULL); @@ -960,12 +968,23 @@ static GtkWidget * sp_gradient_vector_widget_new(SPGradient *gradient, SPStop *s f = gtk_frame_new(_("Stop Color")); gtk_widget_show(f); gtk_box_pack_start(GTK_BOX(vb), f, TRUE, TRUE, PAD); - csel = static_cast<GtkWidget*>(sp_color_selector_new(SP_TYPE_COLOR_NOTEBOOK)); - g_object_set_data(G_OBJECT(vb), "cselector", csel); + + Inkscape::UI::SelectedColor *selected_color = new Inkscape::UI::SelectedColor; + g_object_set_data(G_OBJECT(vb), "cselector", selected_color); + g_object_set_data(G_OBJECT(vb), "updating_color", reinterpret_cast<void*>(0)); + selected_color->signal_dragged.connect(sigc::bind(sigc::ptr_fun(&sp_gradient_vector_color_dragged), selected_color, G_OBJECT(vb))); + selected_color->signal_dragged.connect(sigc::bind(sigc::ptr_fun(&sp_gradient_vector_color_changed), selected_color, G_OBJECT(vb))); + + Gtk::Widget *color_selector = Gtk::manage(new ColorNotebook(*selected_color)); + color_selector->show(); + gtk_container_add(GTK_CONTAINER(f), color_selector->gobj()); + + /* gtk_widget_show(csel); gtk_container_add(GTK_CONTAINER(f), csel); g_signal_connect(G_OBJECT(csel), "dragged", G_CALLBACK(sp_gradient_vector_color_dragged), vb); g_signal_connect(G_OBJECT(csel), "changed", G_CALLBACK(sp_gradient_vector_color_changed), vb); + */ gtk_widget_show(vb); @@ -1126,9 +1145,11 @@ static void sp_gradient_vector_widget_load_gradient(GtkWidget *widget, SPGradien } // get the color selector - SPColorSelector *csel = SP_COLOR_SELECTOR(g_object_get_data(G_OBJECT(widget), "cselector")); + SelectedColor *csel = static_cast<SelectedColor*>(g_object_get_data(G_OBJECT(widget), "cselector")); - csel->base->setColorAlpha( stop->getEffectiveColor(), stop->opacity ); + g_object_set_data(G_OBJECT(widget), "updating_color", reinterpret_cast<void*>(1)); + csel->setColorAlpha(stop->getEffectiveColor(), stop->opacity); + g_object_set_data(G_OBJECT(widget), "updating_color", reinterpret_cast<void*>(0)); /* Fill preview */ GtkWidget *w = static_cast<GtkWidget *>(g_object_get_data(G_OBJECT(widget), "preview")); @@ -1228,6 +1249,12 @@ static void sp_gradient_vector_widget_destroy(GtkObject *object, gpointer /*data sp_repr_remove_listener_by_data(gradient->getRepr(), object); } } + + SelectedColor *selected_color = static_cast<SelectedColor *>(g_object_get_data(G_OBJECT(object), "cselector")); + if (selected_color) { + delete selected_color; + g_object_set_data(G_OBJECT(object), "cselector", NULL); + } } static void sp_gradient_vector_gradient_release(SPObject */*object*/, GtkWidget *widget) @@ -1245,7 +1272,7 @@ static void sp_gradient_vector_gradient_modified(SPObject *object, guint /*flags } } -static void sp_gradient_vector_color_dragged(SPColorSelector *csel, GObject *object) +static void sp_gradient_vector_color_dragged(Inkscape::UI::SelectedColor *selected_color, GObject *object) { SPGradient *gradient, *ngr; @@ -1273,14 +1300,21 @@ static void sp_gradient_vector_color_dragged(SPColorSelector *csel, GObject *obj return; } - csel->base->getColorAlpha(stop->specified_color, stop->opacity); + selected_color->colorAlpha(stop->specified_color, stop->opacity); stop->currentColor = false; blocked = FALSE; } -static void sp_gradient_vector_color_changed(SPColorSelector *csel, GObject *object) +static void sp_gradient_vector_color_changed(Inkscape::UI::SelectedColor *selected_color, GObject *object) { + (void)selected_color; + + void* updating_color = g_object_get_data(G_OBJECT(object), "updating_color"); + if (updating_color) { + return; + } + if (blocked) { return; } @@ -1309,10 +1343,10 @@ static void sp_gradient_vector_color_changed(SPColorSelector *csel, GObject *obj return; } - csel = static_cast<SPColorSelector*>(g_object_get_data(G_OBJECT(object), "cselector")); + SelectedColor *csel = static_cast<SelectedColor *>(g_object_get_data(G_OBJECT(object), "cselector")); SPColor color; float alpha = 0; - csel->base->getColorAlpha( color, alpha ); + csel->colorAlpha(color, alpha); sp_repr_set_css_double(stop->getRepr(), "offset", stop->offset); Inkscape::CSSOStringStream os; diff --git a/src/widgets/paint-selector.cpp b/src/widgets/paint-selector.cpp index 221344296..846ded511 100644 --- a/src/widgets/paint-selector.cpp +++ b/src/widgets/paint-selector.cpp @@ -31,7 +31,6 @@ #include "widgets/widget-sizes.h" #include "xml/repr.h" -#include "sp-color-notebook.h" #include "sp-linear-gradient.h" #include "sp-radial-gradient.h" #include "sp-mesh.h" @@ -48,6 +47,7 @@ #include "io/sys.h" #include "helper/stock-items.h" #include "ui/icon-names.h" +#include "ui/widget/color-notebook.h" #include "paint-selector.h" @@ -58,6 +58,7 @@ #include <gtk/gtk.h> using Inkscape::Widgets::SwatchSelector; +using Inkscape::UI::SelectedColor; enum { MODE_CHANGED, @@ -94,8 +95,7 @@ static gchar const* modeStrings[] = { "MODE_EMPTY", "MODE_MULTIPLE", "MODE_NONE", - "MODE_COLOR_RGB", - "MODE_COLOR_CMYK", + "MODE_SOLID_COLOR", "MODE_GRADIENT_LINEAR", "MODE_GRADIENT_RADIAL", "MODE_PATTERN", @@ -218,7 +218,7 @@ sp_paint_selector_init(SPPaintSelector *psel) psel->none = sp_paint_selector_style_button_add(psel, INKSCAPE_ICON("paint-none"), SPPaintSelector::MODE_NONE, _("No paint")); psel->solid = sp_paint_selector_style_button_add(psel, INKSCAPE_ICON("paint-solid"), - SPPaintSelector::MODE_COLOR_RGB, _("Flat color")); + SPPaintSelector::MODE_SOLID_COLOR, _("Flat color")); psel->gradient = sp_paint_selector_style_button_add(psel, INKSCAPE_ICON("paint-gradient-linear"), SPPaintSelector::MODE_GRADIENT_LINEAR, _("Linear gradient")); psel->radial = sp_paint_selector_style_button_add(psel, INKSCAPE_ICON("paint-gradient-radial"), @@ -292,8 +292,13 @@ sp_paint_selector_init(SPPaintSelector *psel) /* Last used color */ - psel->color.set( 0.0, 0.0, 0.0 ); - psel->alpha = 1.0; + psel->selected_color = new SelectedColor; + psel->updating_color = false; + + psel->selected_color->signal_grabbed.connect(sigc::mem_fun(psel, &SPPaintSelector::onSelectedColorGrabbed)); + psel->selected_color->signal_dragged.connect(sigc::mem_fun(psel, &SPPaintSelector::onSelectedColorDragged)); + psel->selected_color->signal_released.connect(sigc::mem_fun(psel, &SPPaintSelector::onSelectedColorReleased)); + psel->selected_color->signal_changed.connect(sigc::mem_fun(psel, &SPPaintSelector::onSelectedColorChanged)); } static void sp_paint_selector_dispose(GObject *object) @@ -303,6 +308,11 @@ static void sp_paint_selector_dispose(GObject *object) // clean up our long-living pattern menu g_object_set_data(G_OBJECT(psel),"patternmenu",NULL); + if (psel->selected_color) { + delete psel->selected_color; + psel->selected_color = NULL; + } + if ((G_OBJECT_CLASS(sp_paint_selector_parent_class))->dispose) (G_OBJECT_CLASS(sp_paint_selector_parent_class))->dispose(object); } @@ -396,8 +406,7 @@ void SPPaintSelector::setMode(Mode mode) case MODE_NONE: sp_paint_selector_set_mode_none(this); break; - case MODE_COLOR_RGB: - case MODE_COLOR_CMYK: + case MODE_SOLID_COLOR: sp_paint_selector_set_mode_color(this, mode); break; case MODE_GRADIENT_LINEAR: @@ -438,7 +447,6 @@ void SPPaintSelector::setFillrule(FillRule fillrule) void SPPaintSelector::setColorAlpha(SPColor const &color, float alpha) { g_return_if_fail( ( 0.0 <= alpha ) && ( alpha <= 1.0 ) ); - SPColorSelector *csel = 0; /* guint32 rgba = 0; @@ -455,12 +463,13 @@ void SPPaintSelector::setColorAlpha(SPColor const &color, float alpha) #ifdef SP_PS_VERBOSE g_print("PaintSelector set RGBA\n"); #endif - setMode(MODE_COLOR_RGB); + setMode(MODE_SOLID_COLOR); } - csel = reinterpret_cast<SPColorSelector*>(g_object_get_data(G_OBJECT(selector), "color-selector")); + updating_color = true; + selected_color->setColorAlpha(color, alpha); + updating_color = false; //rgba = color.toRGBA32( alpha ); - csel->base->setColorAlpha( color, alpha ); } void SPPaintSelector::setSwatch(SPGradient *vector ) @@ -541,11 +550,7 @@ void SPPaintSelector::getGradientProperties( SPGradientUnits &units, SPGradientS */ void SPPaintSelector::getColorAlpha(SPColor &color, gfloat &alpha) const { - SPColorSelector *csel; - - csel = reinterpret_cast<SPColorSelector*>(g_object_get_data(G_OBJECT(selector), "color-selector")); - - csel->base->getColorAlpha( color, alpha ); + selected_color->colorAlpha(color, alpha); g_assert( ( 0.0 <= alpha ) && ( alpha <= 1.0 ) ); @@ -581,6 +586,9 @@ sp_paint_selector_clear_frame(SPPaintSelector *psel) if (psel->selector) { + //This is a hack to work around GtkNotebook bug in ColorSelector. Is sends signal switch-page on destroy + //The widget is hidden firts so it can recognize that it should not process signals from notebook child + gtk_widget_set_visible(psel->selector, false); gtk_widget_destroy(psel->selector); psel->selector = NULL; } @@ -633,82 +641,82 @@ sp_paint_selector_set_mode_none(SPPaintSelector *psel) /* Color paint */ -static void sp_paint_selector_color_grabbed(SPColorSelector * /*csel*/, SPPaintSelector *psel) -{ - g_signal_emit(G_OBJECT(psel), psel_signals[GRABBED], 0); +void SPPaintSelector::onSelectedColorGrabbed() { + g_signal_emit(G_OBJECT(this), psel_signals[GRABBED], 0); } -static void sp_paint_selector_color_dragged(SPColorSelector * /*csel*/, SPPaintSelector *psel) -{ - g_signal_emit(G_OBJECT(psel), psel_signals[DRAGGED], 0); +void SPPaintSelector::onSelectedColorDragged() { + if (updating_color) { + return; + } + g_signal_emit(G_OBJECT(this), psel_signals[DRAGGED], 0); } -static void sp_paint_selector_color_released(SPColorSelector * /*csel*/, SPPaintSelector *psel) -{ - g_signal_emit(G_OBJECT(psel), psel_signals[RELEASED], 0); +void SPPaintSelector::onSelectedColorReleased() { + g_signal_emit(G_OBJECT(this), psel_signals[RELEASED], 0); } -static void -sp_paint_selector_color_changed(SPColorSelector *csel, SPPaintSelector *psel) -{ - csel->base->getColorAlpha( psel->color, psel->alpha ); +void SPPaintSelector::onSelectedColorChanged() { + if (updating_color) { + return; + } - g_signal_emit(G_OBJECT(psel), psel_signals[CHANGED], 0); + if (mode == MODE_SOLID_COLOR) { + g_signal_emit(G_OBJECT(this), psel_signals[CHANGED], 0); + } else { + g_warning("SPPaintSelector::onSelectedColorChanged(): selected color changed while not in color selection mode"); + } } static void sp_paint_selector_set_mode_color(SPPaintSelector *psel, SPPaintSelector::Mode /*mode*/) { - GtkWidget *csel; - - SPColor newcolor = psel->color; - float newalpha = psel->alpha; - + using Inkscape::UI::Widget::ColorNotebook; + if ((psel->mode == SPPaintSelector::MODE_SWATCH) || (psel->mode == SPPaintSelector::MODE_GRADIENT_LINEAR) || (psel->mode == SPPaintSelector::MODE_GRADIENT_RADIAL) ) { SPGradientSelector *gsel = getGradientFromData(psel); if (gsel) { SPGradient *gradient = gsel->getVector(); - newcolor = gradient->getFirstStop()->specified_color; - newalpha = gradient->getFirstStop()->opacity; + + // Gradient can be null if object paint is changed externally (ie. with a color picker tool) + if (gradient) + { + SPColor color = gradient->getFirstStop()->specified_color; + float alpha = gradient->getFirstStop()->opacity; + psel->selected_color->setColorAlpha(color, alpha, false); + } } } sp_paint_selector_set_style_buttons(psel, psel->solid); gtk_widget_set_sensitive(psel->style, TRUE); - if ((psel->mode == SPPaintSelector::MODE_COLOR_RGB) || (psel->mode == SPPaintSelector::MODE_COLOR_CMYK)) { + if ((psel->mode == SPPaintSelector::MODE_SOLID_COLOR)) { /* Already have color selector */ - csel = GTK_WIDGET(g_object_get_data(G_OBJECT(psel->selector), "color-selector")); + // Do nothing } else { sp_paint_selector_clear_frame(psel); /* Create new color selector */ /* Create vbox */ #if GTK_CHECK_VERSION(3,0,0) - GtkWidget *vb = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4); - gtk_box_set_homogeneous(GTK_BOX(vb), FALSE); + GtkWidget *vb = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4); + gtk_box_set_homogeneous(GTK_BOX(vb), FALSE); #else GtkWidget *vb = gtk_vbox_new(FALSE, 4); #endif gtk_widget_show(vb); /* Color selector */ - csel = sp_color_selector_new( SP_TYPE_COLOR_NOTEBOOK ); - gtk_widget_show(csel); - g_object_set_data(G_OBJECT(vb), "color-selector", csel); - gtk_box_pack_start(GTK_BOX(vb), csel, TRUE, TRUE, 0); - g_signal_connect(G_OBJECT(csel), "grabbed", G_CALLBACK(sp_paint_selector_color_grabbed), psel); - g_signal_connect(G_OBJECT(csel), "dragged", G_CALLBACK(sp_paint_selector_color_dragged), psel); - g_signal_connect(G_OBJECT(csel), "released", G_CALLBACK(sp_paint_selector_color_released), psel); - g_signal_connect(G_OBJECT(csel), "changed", G_CALLBACK(sp_paint_selector_color_changed), psel); + Gtk::Widget *color_selector = Gtk::manage(new ColorNotebook(*(psel->selected_color))); + color_selector->show(); + gtk_box_pack_start(GTK_BOX(vb), color_selector->gobj(), TRUE, TRUE, 0); + /* Pack everything to frame */ gtk_container_add(GTK_CONTAINER(psel->frame), vb); psel->selector = vb; - - /* Set color */ - SP_COLOR_SELECTOR( csel )->base->setColorAlpha( newcolor, newalpha ); } gtk_label_set_markup(GTK_LABEL(psel->label), _("<b>Flat color</b>")); @@ -720,22 +728,22 @@ static void sp_paint_selector_set_mode_color(SPPaintSelector *psel, SPPaintSelec /* Gradient */ -static void sp_paint_selector_gradient_grabbed(SPColorSelector * /*csel*/, SPPaintSelector *psel) +static void sp_paint_selector_gradient_grabbed(SPGradientSelector * /*csel*/, SPPaintSelector *psel) { g_signal_emit(G_OBJECT(psel), psel_signals[GRABBED], 0); } -static void sp_paint_selector_gradient_dragged(SPColorSelector * /*csel*/, SPPaintSelector *psel) +static void sp_paint_selector_gradient_dragged(SPGradientSelector * /*csel*/, SPPaintSelector *psel) { g_signal_emit(G_OBJECT(psel), psel_signals[DRAGGED], 0); } -static void sp_paint_selector_gradient_released(SPColorSelector * /*csel*/, SPPaintSelector *psel) +static void sp_paint_selector_gradient_released(SPGradientSelector * /*csel*/, SPPaintSelector *psel) { g_signal_emit(G_OBJECT(psel), psel_signals[RELEASED], 0); } -static void sp_paint_selector_gradient_changed(SPColorSelector * /*csel*/, SPPaintSelector *psel) +static void sp_paint_selector_gradient_changed(SPGradientSelector * /*csel*/, SPPaintSelector *psel) { g_signal_emit(G_OBJECT(psel), psel_signals[CHANGED], 0); } @@ -838,7 +846,7 @@ ink_pattern_list_get (SPDocument *source) GSList *pl = NULL; GSList const *patterns = source->getResourceList("pattern"); for (GSList *l = const_cast<GSList *>(patterns); l != NULL; l = l->next) { - if (SP_PATTERN(l->data) == pattern_getroot(SP_PATTERN(l->data))) { // only if this is a root pattern + if (SP_PATTERN(l->data) == SP_PATTERN(l->data)->rootPattern()) { // only if this is a root pattern pl = g_slist_prepend(pl, l->data); } } @@ -1158,7 +1166,7 @@ SPPattern *SPPaintSelector::getPattern() } g_free(paturn); } else { - pat = pattern_getroot(SP_PATTERN(patid)); + pat = SP_PATTERN(patid)->rootPattern(); } if (pat && !SP_IS_PATTERN(pat)) { @@ -1265,7 +1273,7 @@ SPPaintSelector::Mode SPPaintSelector::getModeForStyle(SPStyle const & style, Fi } } else if ( target.isColor() ) { // TODO this is no longer a valid assertion: - mode = MODE_COLOR_RGB; // so far only rgb can be read from svg + mode = MODE_SOLID_COLOR; // so far only rgb can be read from svg } else if ( target.isNone() ) { mode = MODE_NONE; } else { diff --git a/src/widgets/paint-selector.h b/src/widgets/paint-selector.h index 788aa673e..23c2dd456 100644 --- a/src/widgets/paint-selector.h +++ b/src/widgets/paint-selector.h @@ -12,12 +12,18 @@ * */ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <glib.h> #include <gtk/gtk.h> #include "color.h" #include "fill-or-stroke.h" #include "sp-gradient-spread.h" #include "sp-gradient-units.h" +#include "ui/selected-color.h" class SPGradient; class SPDesktop; @@ -44,8 +50,7 @@ struct SPPaintSelector { MODE_EMPTY, MODE_MULTIPLE, MODE_NONE, - MODE_COLOR_RGB, - MODE_COLOR_CMYK, + MODE_SOLID_COLOR, MODE_GRADIENT_LINEAR, MODE_GRADIENT_RADIAL, #ifdef WITH_MESH @@ -83,9 +88,8 @@ struct SPPaintSelector { GtkWidget *frame, *selector; GtkWidget *label; - SPColor color; - float alpha; - + Inkscape::UI::SelectedColor *selected_color; + bool updating_color; static Mode getModeForStyle(SPStyle const & style, FillOrStroke kind); @@ -114,6 +118,11 @@ struct SPPaintSelector { // TODO move this elsewhere: void setFlatColor( SPDesktop *desktop, const gchar *color_property, const gchar *opacity_property ); + + void onSelectedColorGrabbed(); + void onSelectedColorDragged(); + void onSelectedColorReleased(); + void onSelectedColorChanged(); }; enum {COMBO_COL_LABEL=0, COMBO_COL_STOCK=1, COMBO_COL_PATTERN=2, COMBO_COL_SEP=3, COMBO_N_COLS=4}; diff --git a/src/widgets/sp-color-icc-selector.cpp b/src/widgets/sp-color-icc-selector.cpp deleted file mode 100644 index 6e910c582..000000000 --- a/src/widgets/sp-color-icc-selector.cpp +++ /dev/null @@ -1,1113 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "gradient-vector.h" -#include <math.h> -#include <gtk/gtk.h> -#include <glibmm/i18n.h> -#include <map> -#include <set> -#include <vector> - -#include "ui/dialog-events.h" -#include "sp-color-icc-selector.h" -#include "sp-color-scales.h" -#include "sp-color-slider.h" -#include "svg/svg-icc-color.h" -#include "colorspace.h" -#include "document.h" -#include "inkscape.h" -#include "profile-manager.h" - -#define noDEBUG_LCMS - -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) -#include "color-profile.h" -#include "cms-system.h" -#include "color-profile-cms-fns.h" - -#ifdef DEBUG_LCMS -#include "preferences.h" -#endif // DEBUG_LCMS -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - - -#ifdef DEBUG_LCMS -extern guint update_in_progress; -#define DEBUG_MESSAGE(key, ...) \ -{\ - Inkscape::Preferences *prefs = Inkscape::Preferences::get();\ - bool dump = prefs->getBool("/options/scislac/" #key);\ - bool dumpD = prefs->getBool("/options/scislac/" #key "D");\ - bool dumpD2 = prefs->getBool("/options/scislac/" #key "D2");\ - dumpD &&= ( (update_in_progress == 0) || dumpD2 );\ - if ( dump )\ - {\ - g_message( __VA_ARGS__ );\ -\ - }\ - if ( dumpD )\ - {\ - GtkWidget *dialog = gtk_message_dialog_new(NULL,\ - GTK_DIALOG_DESTROY_WITH_PARENT, \ - GTK_MESSAGE_INFO, \ - GTK_BUTTONS_OK, \ - __VA_ARGS__ \ - );\ - g_signal_connect_swapped(dialog, "response",\ - G_CALLBACK(gtk_widget_destroy), \ - dialog); \ - gtk_widget_show_all( dialog );\ - }\ -} -#endif // DEBUG_LCMS - - - -G_BEGIN_DECLS - -static void sp_color_icc_selector_dispose(GObject *object); -static void sp_color_icc_selector_show_all (GtkWidget *widget); -static void sp_color_icc_selector_hide(GtkWidget *widget); - -G_END_DECLS - -/** - * Class containing the parts for a single color component's UI presence. - */ -class ComponentUI -{ -public: - ComponentUI() : - _component(), - _adj(0), - _slider(0), - _btn(0), - _label(0), - _map(0) - { - } - - ComponentUI(colorspace::Component const &component) : - _component(component), - _adj(0), - _slider(0), - _btn(0), - _label(0), - _map(0) - { - } - - colorspace::Component _component; - GtkAdjustment *_adj; // Component adjustment - GtkWidget *_slider; - GtkWidget *_btn; // spinbutton - GtkWidget *_label; // Label - guchar *_map; -}; - -/** - * Class that implements the internals of the selector. - */ -class ColorICCSelectorImpl -{ -public: - - ColorICCSelectorImpl( ColorICCSelector *owner); - - ~ColorICCSelectorImpl(); - - static void _adjustmentChanged ( GtkAdjustment *adjustment, SPColorICCSelector *cs ); - - static void _sliderGrabbed( SPColorSlider *slider, SPColorICCSelector *cs ); - static void _sliderReleased( SPColorSlider *slider, SPColorICCSelector *cs ); - static void _sliderChanged( SPColorSlider *slider, SPColorICCSelector *cs ); - - static void _profileSelected( GtkWidget* src, gpointer data ); - static void _fixupHit( GtkWidget* src, gpointer data ); - -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - void _setProfile( SVGICCColor* profile ); - void _switchToProfile( gchar const* name ); -#endif - void _updateSliders( gint ignore ); - void _profilesChanged( std::string const & name ); - - ColorICCSelector *_owner; - - gboolean _updating : 1; - gboolean _dragging : 1; - - guint32 _fixupNeeded; - GtkWidget* _fixupBtn; - GtkWidget* _profileSel; - - std::vector<ComponentUI> _compUI; - - GtkAdjustment* _adj; // Channel adjustment - GtkWidget* _slider; - GtkWidget* _sbtn; // Spinbutton - GtkWidget* _label; // Label - -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - std::string _profileName; - Inkscape::ColorProfile* _prof; - guint _profChannelCount; - gulong _profChangedID; -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) -}; - -#define XPAD 4 -#define YPAD 1 - -namespace -{ - -size_t maxColorspaceComponentCount = 0; - -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - -/** - * Internal variable to track all known colorspaces. - */ -std::set<cmsUInt32Number> knownColorspaces; - -#endif - - -/** - * Simple helper to allow bitwise or on GtkAttachOptions. - */ -GtkAttachOptions operator|(GtkAttachOptions lhs, GtkAttachOptions rhs) -{ - return static_cast<GtkAttachOptions>(static_cast<int>(lhs) | static_cast<int>(rhs)); -} - -/** - * Helper function to handle GTK2/GTK3 attachment #ifdef code. - */ -void attachToGridOrTable(GtkWidget *parent, - GtkWidget *child, - guint left, - guint top, - guint width, - guint height, - bool hexpand = false, - bool centered = false, - guint xpadding = XPAD, - guint ypadding = YPAD) -{ -#if GTK_CHECK_VERSION(3,0,0) - #if GTK_CHECK_VERSION(3,12,0) - gtk_widget_set_margin_start( child, xpadding ); - gtk_widget_set_margin_end( child, xpadding ); - #else - gtk_widget_set_margin_left( child, xpadding ); - gtk_widget_set_margin_right( child, xpadding ); - #endif - - gtk_widget_set_margin_top( child, ypadding ); - gtk_widget_set_margin_bottom( child, ypadding ); - if (hexpand) { - gtk_widget_set_hexpand(child, TRUE); - } - if (centered) { - gtk_widget_set_halign( child, GTK_ALIGN_CENTER ); - gtk_widget_set_valign( child, GTK_ALIGN_CENTER ); - } - gtk_grid_attach( GTK_GRID(parent), child, left, top, width, height ); -#else - GtkAttachOptions xoptions = centered ? static_cast<GtkAttachOptions>(0) : hexpand ? (GTK_EXPAND | GTK_FILL) : GTK_FILL; - GtkAttachOptions yoptions = centered ? static_cast<GtkAttachOptions>(0) : GTK_FILL; - - gtk_table_attach( GTK_TABLE(parent), child, left, left + width, top, top + height, xoptions, yoptions, xpadding, ypadding ); -#endif -} - -} // namespace - -G_DEFINE_TYPE(SPColorICCSelector, sp_color_icc_selector, SP_TYPE_COLOR_SELECTOR); - -static void sp_color_icc_selector_class_init(SPColorICCSelectorClass *klass) -{ - static const gchar* nameset[] = {N_("CMS"), 0}; - GObjectClass *object_class = G_OBJECT_CLASS(klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); - SPColorSelectorClass *selector_class = SP_COLOR_SELECTOR_CLASS (klass); - - selector_class->name = nameset; - selector_class->submode_count = 1; - - object_class->dispose = sp_color_icc_selector_dispose; - - widget_class->show_all = sp_color_icc_selector_show_all; - widget_class->hide = sp_color_icc_selector_hide; -} - - -ColorICCSelector::ColorICCSelector( SPColorSelector* csel ) - : ColorSelector( csel ), - _impl(NULL) -{ -} - -ColorICCSelector::~ColorICCSelector() -{ - if (_impl) - { - delete _impl; - _impl = 0; - } -} - -void sp_color_icc_selector_init(SPColorICCSelector *cs) -{ - SP_COLOR_SELECTOR(cs)->base = new ColorICCSelector( SP_COLOR_SELECTOR(cs) ); - - if ( SP_COLOR_SELECTOR(cs)->base ) - { - SP_COLOR_SELECTOR(cs)->base->init(); - } -} - - -/* -icSigRgbData -icSigCmykData -icSigCmyData -*/ -#define SPACE_ID_RGB 0 -#define SPACE_ID_CMY 1 -#define SPACE_ID_CMYK 2 - - -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) -static cmsUInt16Number* getScratch() { - // bytes per pixel * input channels * width - static cmsUInt16Number* scritch = static_cast<cmsUInt16Number*>(g_new(cmsUInt16Number, 4 * 1024)); - - return scritch; -} - -colorspace::Component::Component() : - name(), - tip(), - scale(1) -{ -} - -colorspace::Component::Component(std::string const &name, std::string const &tip, guint scale) : - name(name), - tip(tip), - scale(scale) -{ -} - -std::vector<colorspace::Component> colorspace::getColorSpaceInfo( uint32_t space ) -{ - static std::map<cmsUInt32Number, std::vector<Component> > sets; - if (sets.empty()) - { - sets[cmsSigXYZData].push_back(Component("_X", "X", 2)); // TYPE_XYZ_16 - sets[cmsSigXYZData].push_back(Component("_Y", "Y", 1)); - sets[cmsSigXYZData].push_back(Component("_Z", "Z", 2)); - - sets[cmsSigLabData].push_back(Component("_L", "L", 100)); // TYPE_Lab_16 - sets[cmsSigLabData].push_back(Component("_a", "a", 256)); - sets[cmsSigLabData].push_back(Component("_b", "b", 256)); - - //cmsSigLuvData - - sets[cmsSigYCbCrData].push_back(Component("_Y", "Y", 1)); // TYPE_YCbCr_16 - sets[cmsSigYCbCrData].push_back(Component("C_b", "Cb", 1)); - sets[cmsSigYCbCrData].push_back(Component("C_r", "Cr", 1)); - - sets[cmsSigYxyData].push_back(Component("_Y", "Y", 1)); // TYPE_Yxy_16 - sets[cmsSigYxyData].push_back(Component("_x", "x", 1)); - sets[cmsSigYxyData].push_back(Component("y", "y", 1)); - - sets[cmsSigRgbData].push_back(Component(_("_R:"), _("Red"), 1)); // TYPE_RGB_16 - sets[cmsSigRgbData].push_back(Component(_("_G:"), _("Green"), 1)); - sets[cmsSigRgbData].push_back(Component(_("_B:"), _("Blue"), 1)); - - sets[cmsSigGrayData].push_back(Component(_("G:"), _("Gray"), 1)); // TYPE_GRAY_16 - - sets[cmsSigHsvData].push_back(Component(_("_H:"), _("Hue"), 360)); // TYPE_HSV_16 - sets[cmsSigHsvData].push_back(Component(_("_S:"), _("Saturation"), 1)); - sets[cmsSigHsvData].push_back(Component("_V:", "Value", 1)); - - sets[cmsSigHlsData].push_back(Component(_("_H:"), _("Hue"), 360)); // TYPE_HLS_16 - sets[cmsSigHlsData].push_back(Component(_("_L:"), _("Lightness"), 1)); - sets[cmsSigHlsData].push_back(Component(_("_S:"), _("Saturation"), 1)); - - sets[cmsSigCmykData].push_back(Component(_("_C:"), _("Cyan"), 1)); // TYPE_CMYK_16 - sets[cmsSigCmykData].push_back(Component(_("_M:"), _("Magenta"), 1)); - sets[cmsSigCmykData].push_back(Component(_("_Y:"), _("Yellow"), 1)); - sets[cmsSigCmykData].push_back(Component(_("_K:"), _("Black"), 1)); - - sets[cmsSigCmyData].push_back(Component(_("_C:"), _("Cyan"), 1)); // TYPE_CMY_16 - sets[cmsSigCmyData].push_back(Component(_("_M:"), _("Magenta"), 1)); - sets[cmsSigCmyData].push_back(Component(_("_Y:"), _("Yellow"), 1)); - - for (std::map<cmsUInt32Number, std::vector<Component> >::iterator it = sets.begin(); it != sets.end(); ++it) - { - knownColorspaces.insert(it->first); - maxColorspaceComponentCount = std::max(maxColorspaceComponentCount, it->second.size()); - } - } - - std::vector<Component> target; - - if (sets.find(space) != sets.end()) - { - target = sets[space]; - } - return target; -} - - -std::vector<colorspace::Component> colorspace::getColorSpaceInfo( Inkscape::ColorProfile *prof ) -{ - return getColorSpaceInfo( asICColorSpaceSig(prof->getColorSpace()) ); -} - -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - -ColorICCSelectorImpl::ColorICCSelectorImpl(ColorICCSelector *owner) : - _owner(owner), - _updating( FALSE ), - _dragging( FALSE ), - _fixupNeeded(0), - _fixupBtn(0), - _profileSel(0), - _compUI(), - _adj(0), - _slider(0), - _sbtn(0), - _label(0) -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - , - _profileName(), - _prof(0), - _profChannelCount(0), - _profChangedID(0) -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) -{ -} - -ColorICCSelectorImpl::~ColorICCSelectorImpl() -{ - _adj = 0; - _sbtn = 0; - _label = 0; -} - -void ColorICCSelector::init() -{ - if (_impl) delete(_impl); - _impl = new ColorICCSelectorImpl(this); - gint row = 0; - - _impl->_updating = FALSE; - _impl->_dragging = FALSE; - -#if GTK_CHECK_VERSION(3,0,0) - GtkWidget *t = gtk_grid_new(); -#else - GtkWidget *t = gtk_table_new(5, 3, FALSE); -#endif - - gtk_widget_show (t); - gtk_box_pack_start (GTK_BOX (_csel), t, TRUE, TRUE, 4); - - _impl->_compUI.clear(); - - // Create components - row = 0; - - - _impl->_fixupBtn = gtk_button_new_with_label(_("Fix")); - g_signal_connect( G_OBJECT(_impl->_fixupBtn), "clicked", G_CALLBACK(ColorICCSelectorImpl::_fixupHit), (gpointer)_impl ); - gtk_widget_set_sensitive( _impl->_fixupBtn, FALSE ); - gtk_widget_set_tooltip_text( _impl->_fixupBtn, _("Fix RGB fallback to match icc-color() value.") ); - //gtk_misc_set_alignment( GTK_MISC (_impl->_fixupBtn), 1.0, 0.5 ); - gtk_widget_show( _impl->_fixupBtn ); - - attachToGridOrTable(t, _impl->_fixupBtn, 0, row, 1, 1); - - // Combobox and store with 2 columns : label (0) and full name (1) - GtkListStore *store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); - _impl->_profileSel = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store)); - - GtkCellRenderer *renderer = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(_impl->_profileSel), renderer, TRUE); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(_impl->_profileSel), renderer, "text", 0, NULL); - - GtkTreeIter iter; - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, 0, _("<none>"), 1, _("<none>"), -1); - - gtk_widget_show( _impl->_profileSel ); - gtk_combo_box_set_active( GTK_COMBO_BOX(_impl->_profileSel), 0 ); - - attachToGridOrTable(t, _impl->_profileSel, 1, row, 1, 1); - -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - _impl->_profChangedID = g_signal_connect( G_OBJECT(_impl->_profileSel), "changed", G_CALLBACK(ColorICCSelectorImpl::_profileSelected), (gpointer)_impl ); -#else - gtk_widget_set_sensitive( _impl->_profileSel, false ); -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - - - row++; - - // populate the data for colorspaces and channels: -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - std::vector<colorspace::Component> things = colorspace::getColorSpaceInfo( cmsSigRgbData ); -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - - for ( size_t i = 0; i < maxColorspaceComponentCount; i++ ) { -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - if (i < things.size()) { - _impl->_compUI.push_back(ComponentUI(things[i])); - } else { - _impl->_compUI.push_back(ComponentUI()); - } - - std::string labelStr = (i < things.size()) ? things[i].name.c_str() : ""; -#else - _impl->_compUI.push_back(ComponentUI()); - - std::string labelStr = "."; -#endif - - _impl->_compUI[i]._label = gtk_label_new_with_mnemonic( labelStr.c_str() ); - gtk_misc_set_alignment( GTK_MISC (_impl->_compUI[i]._label), 1.0, 0.5 ); - gtk_widget_show( _impl->_compUI[i]._label ); - - attachToGridOrTable(t, _impl->_compUI[i]._label, 0, row, 1, 1); - - // Adjustment - guint scaleValue = _impl->_compUI[i]._component.scale; - gdouble step = static_cast<gdouble>(scaleValue) / 100.0; - gdouble page = static_cast<gdouble>(scaleValue) / 10.0; - gint digits = (step > 0.9) ? 0 : 2; - _impl->_compUI[i]._adj = GTK_ADJUSTMENT( gtk_adjustment_new( 0.0, 0.0, scaleValue, step, page, page ) ); - - // Slider - _impl->_compUI[i]._slider = sp_color_slider_new( _impl->_compUI[i]._adj ); -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - gtk_widget_set_tooltip_text( _impl->_compUI[i]._slider, (i < things.size()) ? things[i].tip.c_str() : "" ); -#else - gtk_widget_set_tooltip_text( _impl->_compUI[i]._slider, "." ); -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - gtk_widget_show( _impl->_compUI[i]._slider ); - - attachToGridOrTable(t, _impl->_compUI[i]._slider, 1, row, 1, 1, true); - - _impl->_compUI[i]._btn = gtk_spin_button_new( _impl->_compUI[i]._adj, step, digits ); -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - gtk_widget_set_tooltip_text( _impl->_compUI[i]._btn, (i < things.size()) ? things[i].tip.c_str() : "" ); -#else - gtk_widget_set_tooltip_text( _impl->_compUI[i]._btn, "." ); -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - sp_dialog_defocus_on_enter( _impl->_compUI[i]._btn ); - gtk_label_set_mnemonic_widget( GTK_LABEL(_impl->_compUI[i]._label), _impl->_compUI[i]._btn ); - gtk_widget_show( _impl->_compUI[i]._btn ); - - attachToGridOrTable(t, _impl->_compUI[i]._btn, 2, row, 1, 1, false, true); - - _impl->_compUI[i]._map = g_new( guchar, 4 * 1024 ); - memset( _impl->_compUI[i]._map, 0x0ff, 1024 * 4 ); - - - // Signals - g_signal_connect( G_OBJECT( _impl->_compUI[i]._adj ), "value_changed", G_CALLBACK( ColorICCSelectorImpl::_adjustmentChanged ), _csel ); - - g_signal_connect( G_OBJECT( _impl->_compUI[i]._slider ), "grabbed", G_CALLBACK( ColorICCSelectorImpl::_sliderGrabbed ), _csel ); - g_signal_connect( G_OBJECT( _impl->_compUI[i]._slider ), "released", G_CALLBACK( ColorICCSelectorImpl::_sliderReleased ), _csel ); - g_signal_connect( G_OBJECT( _impl->_compUI[i]._slider ), "changed", G_CALLBACK( ColorICCSelectorImpl::_sliderChanged ), _csel ); - - row++; - } - - // Label - _impl->_label = gtk_label_new_with_mnemonic(_("_A:")); - gtk_misc_set_alignment(GTK_MISC(_impl->_label), 1.0, 0.5); - gtk_widget_show(_impl->_label); - - attachToGridOrTable(t, _impl->_label, 0, row, 1, 1); - - // Adjustment - _impl->_adj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 255.0, 1.0, 10.0, 10.0)); - - // Slider - _impl->_slider = sp_color_slider_new(_impl->_adj); - gtk_widget_set_tooltip_text(_impl->_slider, _("Alpha (opacity)")); - gtk_widget_show(_impl->_slider); - - attachToGridOrTable(t, _impl->_slider, 1, row, 1, 1, true); - - sp_color_slider_set_colors( SP_COLOR_SLIDER( _impl->_slider ), - SP_RGBA32_F_COMPOSE( 1.0, 1.0, 1.0, 0.0 ), - SP_RGBA32_F_COMPOSE( 1.0, 1.0, 1.0, 0.5 ), - SP_RGBA32_F_COMPOSE( 1.0, 1.0, 1.0, 1.0 ) ); - - - // Spinbutton - _impl->_sbtn = gtk_spin_button_new(GTK_ADJUSTMENT(_impl->_adj), 1.0, 0); - gtk_widget_set_tooltip_text(_impl->_sbtn, _("Alpha (opacity)")); - sp_dialog_defocus_on_enter(_impl->_sbtn); - gtk_label_set_mnemonic_widget(GTK_LABEL(_impl->_label), _impl->_sbtn); - gtk_widget_show(_impl->_sbtn); - - attachToGridOrTable(t, _impl->_sbtn, 2, row, 1, 1, false, true); - - // Signals - g_signal_connect(G_OBJECT(_impl->_adj), "value_changed", G_CALLBACK(ColorICCSelectorImpl::_adjustmentChanged), _csel); - - g_signal_connect(G_OBJECT(_impl->_slider), "grabbed", G_CALLBACK(ColorICCSelectorImpl::_sliderGrabbed), _csel); - g_signal_connect(G_OBJECT(_impl->_slider), "released", G_CALLBACK(ColorICCSelectorImpl::_sliderReleased), _csel); - g_signal_connect(G_OBJECT(_impl->_slider), "changed", G_CALLBACK(ColorICCSelectorImpl::_sliderChanged), _csel); -} - -static void sp_color_icc_selector_dispose(GObject *object) -{ - if (G_OBJECT_CLASS(sp_color_icc_selector_parent_class)->dispose) { - G_OBJECT_CLASS(sp_color_icc_selector_parent_class)->dispose(object); - } -} - -static void -sp_color_icc_selector_show_all (GtkWidget *widget) -{ - gtk_widget_show (widget); -} - -static void sp_color_icc_selector_hide(GtkWidget *widget) -{ - gtk_widget_hide(widget); -} - -GtkWidget * -sp_color_icc_selector_new (void) -{ - SPColorICCSelector *csel; - - csel = static_cast<SPColorICCSelector*>(g_object_new (SP_TYPE_COLOR_ICC_SELECTOR, NULL)); - - return GTK_WIDGET (csel); -} - - -void ColorICCSelectorImpl::_fixupHit( GtkWidget* /*src*/, gpointer data ) -{ - ColorICCSelectorImpl* self = reinterpret_cast<ColorICCSelectorImpl*>(data); - gtk_widget_set_sensitive( self->_fixupBtn, FALSE ); - self->_adjustmentChanged( self->_compUI[0]._adj, SP_COLOR_ICC_SELECTOR(self->_owner->_csel) ); -} - -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) -void ColorICCSelectorImpl::_profileSelected( GtkWidget* /*src*/, gpointer data ) -{ - ColorICCSelectorImpl* self = reinterpret_cast<ColorICCSelectorImpl*>(data); - - GtkTreeIter iter; - if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(self->_profileSel), &iter)) { - GtkTreeModel *store = gtk_combo_box_get_model(GTK_COMBO_BOX(self->_profileSel)); - gchar* name = 0; - - gtk_tree_model_get(store, &iter, 1, &name, -1); - self->_switchToProfile( name ); - gtk_widget_set_tooltip_text(self->_profileSel, name ); - - if ( name ) { - g_free( name ); - } - } -} -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) -void ColorICCSelectorImpl::_switchToProfile( gchar const* name ) -{ - bool dirty = false; - SPColor tmp( _owner->_color ); - - if ( name ) { - if ( tmp.icc && tmp.icc->colorProfile == name ) { -#ifdef DEBUG_LCMS - g_message("Already at name [%s]", name ); -#endif // DEBUG_LCMS - } else { -#ifdef DEBUG_LCMS - g_message("Need to switch to profile [%s]", name ); -#endif // DEBUG_LCMS - if ( tmp.icc ) { - tmp.icc->colors.clear(); - } else { - tmp.icc = new SVGICCColor(); - } - tmp.icc->colorProfile = name; - Inkscape::ColorProfile* newProf = SP_ACTIVE_DOCUMENT->profileManager->find(name); - if ( newProf ) { - cmsHTRANSFORM trans = newProf->getTransfFromSRGB8(); - if ( trans ) { - guint32 val = _owner->_color.toRGBA32(0); - guchar pre[4] = { - static_cast<guchar>(SP_RGBA32_R_U(val)), - static_cast<guchar>(SP_RGBA32_G_U(val)), - static_cast<guchar>(SP_RGBA32_B_U(val)), - 255}; -#ifdef DEBUG_LCMS - g_message("Shoving in [%02x] [%02x] [%02x]", pre[0], pre[1], pre[2]); -#endif // DEBUG_LCMS - cmsUInt16Number post[4] = {0,0,0,0}; - cmsDoTransform( trans, pre, post, 1 ); -#ifdef DEBUG_LCMS - g_message("got on out [%04x] [%04x] [%04x] [%04x]", post[0], post[1], post[2], post[3]); -#endif // DEBUG_LCMS -#if HAVE_LIBLCMS1 - guint count = _cmsChannelsOf( asICColorSpaceSig(newProf->getColorSpace()) ); -#elif HAVE_LIBLCMS2 - guint count = cmsChannelsOf( asICColorSpaceSig(newProf->getColorSpace()) ); -#endif - - std::vector<colorspace::Component> things = colorspace::getColorSpaceInfo(asICColorSpaceSig(newProf->getColorSpace())); - - for ( guint i = 0; i < count; i++ ) { - gdouble val = (((gdouble)post[i])/65535.0) * (gdouble)((i < things.size()) ? things[i].scale : 1); -#ifdef DEBUG_LCMS - g_message(" scaled %d by %d to be %f", i, ((i < things.size()) ? things[i].scale : 1), val); -#endif // DEBUG_LCMS - tmp.icc->colors.push_back(val); - } - cmsHTRANSFORM retrans = newProf->getTransfToSRGB8(); - if ( retrans ) { - cmsDoTransform( retrans, post, pre, 1 ); -#ifdef DEBUG_LCMS - g_message(" back out [%02x] [%02x] [%02x]", pre[0], pre[1], pre[2]); -#endif // DEBUG_LCMS - tmp.set(SP_RGBA32_U_COMPOSE(pre[0], pre[1], pre[2], 0xff)); - } - } - } - dirty = true; - } - } else { -#ifdef DEBUG_LCMS - g_message("NUKE THE ICC"); -#endif // DEBUG_LCMS - if ( tmp.icc ) { - delete tmp.icc; - tmp.icc = 0; - dirty = true; - _fixupHit( 0, this ); - } else { -#ifdef DEBUG_LCMS - g_message("No icc to nuke"); -#endif // DEBUG_LCMS - } - } - - if ( dirty ) { -#ifdef DEBUG_LCMS - g_message("+----------------"); - g_message("+ new color is [%s]", tmp.toString().c_str()); -#endif // DEBUG_LCMS - _setProfile( tmp.icc ); - //_adjustmentChanged( _compUI[0]._adj, SP_COLOR_ICC_SELECTOR(_csel) ); - _owner->setColorAlpha( tmp, _owner->_alpha, true ); -#ifdef DEBUG_LCMS - g_message("+_________________"); -#endif // DEBUG_LCMS - } -} -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) -void ColorICCSelectorImpl::_profilesChanged( std::string const & name ) -{ - GtkComboBox* combo = GTK_COMBO_BOX(_profileSel); - - g_signal_handler_block( G_OBJECT(_profileSel), _profChangedID ); - - GtkListStore *store = GTK_LIST_STORE(gtk_combo_box_get_model(combo)); - gtk_list_store_clear(store); - - GtkTreeIter iter; - gtk_list_store_append (store, &iter); - gtk_list_store_set(store, &iter, 0, _("<none>"), 1, _("<none>"), -1); - - gtk_combo_box_set_active( combo, 0 ); - - int index = 1; - const GSList *current = SP_ACTIVE_DOCUMENT->getResourceList( "iccprofile" ); - while ( current ) { - SPObject* obj = SP_OBJECT(current->data); - Inkscape::ColorProfile* prof = reinterpret_cast<Inkscape::ColorProfile*>(obj); - - gtk_list_store_append (store, &iter); - gtk_list_store_set(store, &iter, 0, gr_ellipsize_text(prof->name, 25).c_str(), 1, prof->name, -1); - - if ( name == prof->name ) { - gtk_combo_box_set_active( combo, index ); - gtk_widget_set_tooltip_text(_profileSel, prof->name ); - } - - index++; - current = g_slist_next(current); - } - - g_signal_handler_unblock( G_OBJECT(_profileSel), _profChangedID ); -} -#else -void ColorICCSelectorImpl::_profilesChanged( std::string const & /*name*/ ) -{ -} -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - -// Helpers for setting color value - -void ColorICCSelector::_colorChanged() -{ - _impl->_updating = TRUE; - //sp_color_icc_set_color( SP_COLOR_ICC( _icc ), &color ); - -#ifdef DEBUG_LCMS - g_message( "/^^^^^^^^^ %p::_colorChanged(%08x:%s)", this, - _color.toRGBA32(_alpha), ( (_color.icc) ? _color.icc->colorProfile.c_str(): "<null>" ) - ); -#endif // DEBUG_LCMS - -#ifdef DEBUG_LCMS - g_message("FLIPPIES!!!! %p '%s'", _color.icc, (_color.icc ? _color.icc->colorProfile.c_str():"<null>")); -#endif // DEBUG_LCMS - - _impl->_profilesChanged( (_color.icc) ? _color.icc->colorProfile : std::string("") ); - ColorScales::setScaled( _impl->_adj, _alpha ); - -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - _impl->_setProfile( _color.icc ); - _impl->_fixupNeeded = 0; - gtk_widget_set_sensitive( _impl->_fixupBtn, FALSE ); - - if (_impl->_prof) { - if (_impl->_prof->getTransfToSRGB8() ) { - cmsUInt16Number tmp[4]; - for ( guint i = 0; i < _impl->_profChannelCount; i++ ) { - gdouble val = 0.0; - if ( _color.icc->colors.size() > i ) { - if ( _impl->_compUI[i]._component.scale == 256 ) { - val = (_color.icc->colors[i] + 128.0) / static_cast<gdouble>(_impl->_compUI[i]._component.scale); - } else { - val = _color.icc->colors[i] / static_cast<gdouble>(_impl->_compUI[i]._component.scale); - } - } - tmp[i] = val * 0x0ffff; - } - guchar post[4] = {0,0,0,0}; - cmsHTRANSFORM trans = _impl->_prof->getTransfToSRGB8(); - if ( trans ) { - cmsDoTransform( trans, tmp, post, 1 ); - guint32 other = SP_RGBA32_U_COMPOSE(post[0], post[1], post[2], 255 ); - if ( other != _color.toRGBA32(255) ) { - _impl->_fixupNeeded = other; - gtk_widget_set_sensitive( _impl->_fixupBtn, TRUE ); -#ifdef DEBUG_LCMS - g_message("Color needs to change 0x%06x to 0x%06x", _color.toRGBA32(255) >> 8, other >> 8 ); -#endif // DEBUG_LCMS - } - } - } - } -#else - //(void)color; -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - _impl->_updateSliders( -1 ); - - - _impl->_updating = FALSE; -#ifdef DEBUG_LCMS - g_message( "\\_________ %p::_colorChanged()", this ); -#endif // DEBUG_LCMS -} - -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) -void ColorICCSelectorImpl::_setProfile( SVGICCColor* profile ) -{ -#ifdef DEBUG_LCMS - g_message( "/^^^^^^^^^ %p::_setProfile(%s)", this, - ( (profile) ? profile->colorProfile.c_str() : "<null>") - ); -#endif // DEBUG_LCMS - bool profChanged = false; - if ( _prof && (!profile || (_profileName != profile->colorProfile) ) ) { - // Need to clear out the prior one - profChanged = true; - _profileName.clear(); - _prof = 0; - _profChannelCount = 0; - } else if ( profile && !_prof ) { - profChanged = true; - } - - for ( size_t i = 0; i < _compUI.size(); i++ ) { - gtk_widget_hide( _compUI[i]._label ); - gtk_widget_hide( _compUI[i]._slider ); - gtk_widget_hide( _compUI[i]._btn ); - } - - if ( profile ) { - _prof = SP_ACTIVE_DOCUMENT->profileManager->find(profile->colorProfile.c_str()); - if ( _prof && (asICColorProfileClassSig(_prof->getProfileClass()) != cmsSigNamedColorClass) ) { -#if HAVE_LIBLCMS1 - _profChannelCount = _cmsChannelsOf( asICColorSpaceSig(_prof->getColorSpace()) ); -#elif HAVE_LIBLCMS2 - _profChannelCount = cmsChannelsOf( asICColorSpaceSig(_prof->getColorSpace()) ); -#endif - - if ( profChanged ) { - std::vector<colorspace::Component> things = colorspace::getColorSpaceInfo(asICColorSpaceSig(_prof->getColorSpace())); - for (size_t i = 0; (i < things.size()) && (i < _profChannelCount); ++i) - { - _compUI[i]._component = things[i]; - } - - for ( guint i = 0; i < _profChannelCount; i++ ) { - gtk_label_set_text_with_mnemonic( GTK_LABEL(_compUI[i]._label), (i < things.size()) ? things[i].name.c_str() : ""); - - gtk_widget_set_tooltip_text( _compUI[i]._slider, (i < things.size()) ? things[i].tip.c_str() : "" ); - gtk_widget_set_tooltip_text( _compUI[i]._btn, (i < things.size()) ? things[i].tip.c_str() : "" ); - - sp_color_slider_set_colors( SP_COLOR_SLIDER(_compUI[i]._slider), - SPColor(0.0, 0.0, 0.0).toRGBA32(0xff), - SPColor(0.5, 0.5, 0.5).toRGBA32(0xff), - SPColor(1.0, 1.0, 1.0).toRGBA32(0xff) ); -/* - _compUI[i]._adj = GTK_ADJUSTMENT( gtk_adjustment_new( val, 0.0, _fooScales[i], step, page, page ) ); - g_signal_connect( G_OBJECT( _compUI[i]._adj ), "value_changed", G_CALLBACK( _adjustmentChanged ), _csel ); - - sp_color_slider_set_adjustment( SP_COLOR_SLIDER(_compUI[i]._slider), _compUI[i]._adj ); - gtk_spin_button_set_adjustment( GTK_SPIN_BUTTON(_compUI[i]._btn), _compUI[i]._adj ); - gtk_spin_button_set_digits( GTK_SPIN_BUTTON(_compUI[i]._btn), digits ); -*/ - gtk_widget_show( _compUI[i]._label ); - gtk_widget_show( _compUI[i]._slider ); - gtk_widget_show( _compUI[i]._btn ); - //gtk_adjustment_set_value( _compUI[i]._adj, 0.0 ); - //gtk_adjustment_set_value( _compUI[i]._adj, val ); - } - for ( size_t i = _profChannelCount; i < _compUI.size(); i++ ) { - gtk_widget_hide( _compUI[i]._label ); - gtk_widget_hide( _compUI[i]._slider ); - gtk_widget_hide( _compUI[i]._btn ); - } - } - } else { - // Give up for now on named colors - _prof = 0; - } - } - -#ifdef DEBUG_LCMS - g_message( "\\_________ %p::_setProfile()", this ); -#endif // DEBUG_LCMS -} -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - -void ColorICCSelectorImpl::_updateSliders( gint ignore ) -{ -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - if ( _owner->_color.icc ) - { - for ( guint i = 0; i < _profChannelCount; i++ ) { - gdouble val = 0.0; - if ( _owner->_color.icc->colors.size() > i ) { - if ( _compUI[i]._component.scale == 256 ) { - val = (_owner->_color.icc->colors[i] + 128.0) / static_cast<gdouble>(_compUI[i]._component.scale); - } else { - val = _owner->_color.icc->colors[i] / static_cast<gdouble>(_compUI[i]._component.scale); - } - } - gtk_adjustment_set_value( _compUI[i]._adj, val ); - } - - if ( _prof ) { - if ( _prof->getTransfToSRGB8() ) { - for ( guint i = 0; i < _profChannelCount; i++ ) { - if ( static_cast<gint>(i) != ignore ) { - cmsUInt16Number* scratch = getScratch(); - cmsUInt16Number filler[4] = {0, 0, 0, 0}; - for ( guint j = 0; j < _profChannelCount; j++ ) { - filler[j] = 0x0ffff * ColorScales::getScaled( _compUI[j]._adj ); - } - - cmsUInt16Number* p = scratch; - for ( guint x = 0; x < 1024; x++ ) { - for ( guint j = 0; j < _profChannelCount; j++ ) { - if ( j == i ) { - *p++ = x * 0x0ffff / 1024; - } else { - *p++ = filler[j]; - } - } - } - - cmsHTRANSFORM trans = _prof->getTransfToSRGB8(); - if ( trans ) { - cmsDoTransform( trans, scratch, _compUI[i]._map, 1024 ); - sp_color_slider_set_map( SP_COLOR_SLIDER(_compUI[i]._slider), _compUI[i]._map ); - } - } - } - } - } - } -#else - (void)ignore; -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - - guint32 start = _owner->_color.toRGBA32( 0x00 ); - guint32 mid = _owner->_color.toRGBA32( 0x7f ); - guint32 end = _owner->_color.toRGBA32( 0xff ); - - sp_color_slider_set_colors( SP_COLOR_SLIDER(_slider), start, mid, end ); -} - - -void ColorICCSelectorImpl::_adjustmentChanged( GtkAdjustment *adjustment, SPColorICCSelector *cs ) -{ -// // TODO check this. It looks questionable: -// // if a value is entered between 0 and 1 exclusive, normalize it to (int) 0..255 or 0..100 -// if (adjustment->value > 0.0 && adjustment->value < 1.0) { -// gtk_adjustment_set_value( adjustment, floor ((adjustment->value) * adjustment->upper + 0.5) ); -// } - -#ifdef DEBUG_LCMS - g_message( "/^^^^^^^^^ %p::_adjustmentChanged()", cs ); -#endif // DEBUG_LCMS - - ColorICCSelector* iccSelector = static_cast<ColorICCSelector*>(SP_COLOR_SELECTOR(cs)->base); - if (iccSelector->_impl->_updating) { - return; - } - - iccSelector->_impl->_updating = TRUE; - - gint match = -1; - - SPColor newColor( iccSelector->_color ); - gfloat scaled = ColorScales::getScaled( iccSelector->_impl->_adj ); - if ( iccSelector->_impl->_adj == adjustment ) { -#ifdef DEBUG_LCMS - g_message("ALPHA"); -#endif // DEBUG_LCMS - } else { -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - for ( size_t i = 0; i < iccSelector->_impl->_compUI.size(); i++ ) { - if ( iccSelector->_impl->_compUI[i]._adj == adjustment ) { - match = i; - break; - } - } - if ( match >= 0 ) { -#ifdef DEBUG_LCMS - g_message(" channel %d", match ); -#endif // DEBUG_LCMS - } - - - cmsUInt16Number tmp[4]; - for ( guint i = 0; i < 4; i++ ) { - tmp[i] = ColorScales::getScaled( iccSelector->_impl->_compUI[i]._adj ) * 0x0ffff; - } - guchar post[4] = {0,0,0,0}; - - cmsHTRANSFORM trans = iccSelector->_impl->_prof->getTransfToSRGB8(); - if ( trans ) { - cmsDoTransform( trans, tmp, post, 1 ); - } - - SPColor other( SP_RGBA32_U_COMPOSE(post[0], post[1], post[2], 255) ); - other.icc = new SVGICCColor(); - if ( iccSelector->_color.icc ) { - other.icc->colorProfile = iccSelector->_color.icc->colorProfile; - } - - guint32 prior = iccSelector->_color.toRGBA32(255); - guint32 newer = other.toRGBA32(255); - - if ( prior != newer ) { -#ifdef DEBUG_LCMS - g_message("Transformed color from 0x%08x to 0x%08x", prior, newer ); - g_message(" ~~~~ FLIP"); -#endif // DEBUG_LCMS - newColor = other; - newColor.icc->colors.clear(); - for ( guint i = 0; i < iccSelector->_impl->_profChannelCount; i++ ) { - gdouble val = ColorScales::getScaled( iccSelector->_impl->_compUI[i]._adj ); - val *= iccSelector->_impl->_compUI[i]._component.scale; - if ( iccSelector->_impl->_compUI[i]._component.scale == 256 ) { - val -= 128; - } - newColor.icc->colors.push_back( val ); - } - } -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - } - iccSelector->_updateInternals( newColor, scaled, iccSelector->_impl->_dragging ); - iccSelector->_impl->_updateSliders( match ); - - iccSelector->_impl->_updating = FALSE; -#ifdef DEBUG_LCMS - g_message( "\\_________ %p::_adjustmentChanged()", cs ); -#endif // DEBUG_LCMS -} - -void ColorICCSelectorImpl::_sliderGrabbed( SPColorSlider * /*slider*/, SPColorICCSelector * /*cs*/ ) -{ -// ColorICCSelector* iccSelector = dynamic_cast<ColorICCSelector*>(SP_COLOR_SELECTOR(cs)->base); -// if (!iccSelector->_dragging) { -// iccSelector->_dragging = TRUE; -// iccSelector->_grabbed(); -// iccSelector->_updateInternals( iccSelector->_color, ColorScales::getScaled( iccSelector->_impl->_adj ), iccSelector->_dragging ); -// } -} - -void ColorICCSelectorImpl::_sliderReleased( SPColorSlider * /*slider*/, SPColorICCSelector * /*cs*/ ) -{ -// ColorICCSelector* iccSelector = dynamic_cast<ColorICCSelector*>(SP_COLOR_SELECTOR(cs)->base); -// if (iccSelector->_dragging) { -// iccSelector->_dragging = FALSE; -// iccSelector->_released(); -// iccSelector->_updateInternals( iccSelector->_color, ColorScales::getScaled( iccSelector->_adj ), iccSelector->_dragging ); -// } -} - -#ifdef DEBUG_LCMS -void ColorICCSelectorImpl::_sliderChanged( SPColorSlider *slider, SPColorICCSelector *cs ) -#else -void ColorICCSelectorImpl::_sliderChanged( SPColorSlider * /*slider*/, SPColorICCSelector * /*cs*/ ) -#endif // DEBUG_LCMS -{ -#ifdef DEBUG_LCMS - g_message("Changed %p and %p", slider, cs ); -#endif // DEBUG_LCMS -// ColorICCSelector* iccSelector = dynamic_cast<ColorICCSelector*>(SP_COLOR_SELECTOR(cs)->base); - -// iccSelector->_updateInternals( iccSelector->_color, ColorScales::getScaled( iccSelector->_adj ), iccSelector->_dragging ); -} - - -/* - 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 : diff --git a/src/widgets/sp-color-icc-selector.h b/src/widgets/sp-color-icc-selector.h deleted file mode 100644 index 6cdaff639..000000000 --- a/src/widgets/sp-color-icc-selector.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef SEEN_SP_COLOR_ICC_SELECTOR_H -#define SEEN_SP_COLOR_ICC_SELECTOR_H - -#include <glib.h> -#include "sp-color-selector.h" - -namespace Inkscape { -class ColorProfile; -} - -struct SPColorICCSelector; -struct SPColorICCSelectorClass; - -class ColorICCSelectorImpl; - -class ColorICCSelector: public ColorSelector -{ -public: - ColorICCSelector( SPColorSelector* csel ); - virtual ~ColorICCSelector(); - - virtual void init(); - -protected: - virtual void _colorChanged(); - - void _recalcColor( gboolean changing ); - -private: - friend class ColorICCSelectorImpl; - - // By default, disallow copy constructor and assignment operator - ColorICCSelector( const ColorICCSelector& obj ); - ColorICCSelector& operator=( const ColorICCSelector& obj ); - - ColorICCSelectorImpl *_impl; -}; - - - -#define SP_TYPE_COLOR_ICC_SELECTOR (sp_color_icc_selector_get_type()) -#define SP_COLOR_ICC_SELECTOR(o) (G_TYPE_CHECK_INSTANCE_CAST((o), SP_TYPE_COLOR_ICC_SELECTOR, SPColorICCSelector)) -#define SP_COLOR_ICC_SELECTOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), SP_TYPE_COLOR_ICC_SELECTOR, SPColorICCSelectorClass)) -#define SP_IS_COLOR_ICC_SELECTOR(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), SP_TYPE_COLOR_ICC_SELECTOR)) -#define SP_IS_COLOR_ICC_SELECTOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), SP_TYPE_COLOR_ICC_SELECTOR)) - -struct SPColorICCSelector { - SPColorSelector parent; -}; - -struct SPColorICCSelectorClass { - SPColorSelectorClass parent_class; -}; - -GType sp_color_icc_selector_get_type(void); - -GtkWidget *sp_color_icc_selector_new(void); - - - -#endif // SEEN_SP_COLOR_ICC_SELECTOR_H - -/* - 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 : diff --git a/src/widgets/sp-color-notebook.cpp b/src/widgets/sp-color-notebook.cpp deleted file mode 100644 index c7fa96efd..000000000 --- a/src/widgets/sp-color-notebook.cpp +++ /dev/null @@ -1,826 +0,0 @@ -/* - * A notebook with RGB, CMYK, CMS, HSL, and Wheel pages - * - * Author: - * Lauris Kaplinski <lauris@kaplinski.com> - * bulia byak <buliabyak@users.sf.net> - * - * Copyright (C) 2001-2002 Lauris Kaplinski - * - * This code is in public domain - */ - -#undef SPCS_PREVIEW -#define noDUMP_CHANGE_INFO - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "widgets/icon.h" -#include <cstring> -#include <string> -#include <cstdlib> -#include <cstddef> -#include <gtk/gtk.h> -#include <glibmm/i18n.h> - -#include "ui/dialog-events.h" -#include "../preferences.h" -#include "sp-color-notebook.h" -#include "spw-utilities.h" -#include "sp-color-scales.h" -#include "sp-color-icc-selector.h" -#include "sp-color-wheel-selector.h" -#include "svg/svg-icc-color.h" -#include "../inkscape.h" -#include "../document.h" -#include "../profile-manager.h" -#include "color-profile.h" -#include "cms-system.h" -#include "ui/tools-switch.h" -#include "ui/tools/tool-base.h" - -using Inkscape::CMSSystem; - -struct SPColorNotebookTracker { - const gchar* name; - const gchar* className; - GType type; - guint submode; - gboolean enabledFull; - gboolean enabledBrief; - SPColorNotebook *backPointer; -}; - -static void sp_color_notebook_dispose(GObject *object); - -static void sp_color_notebook_show_all (GtkWidget *widget); -static void sp_color_notebook_hide(GtkWidget *widget); - -#define XPAD 4 -#define YPAD 1 - -G_DEFINE_TYPE(SPColorNotebook, sp_color_notebook, SP_TYPE_COLOR_SELECTOR); - -static void sp_color_notebook_class_init(SPColorNotebookClass *klass) -{ - GObjectClass *object_class = reinterpret_cast<GObjectClass *>(klass); - GtkWidgetClass *widget_class = reinterpret_cast<GtkWidgetClass *>(klass); - - object_class->dispose = sp_color_notebook_dispose; - - widget_class->show_all = sp_color_notebook_show_all; - widget_class->hide = sp_color_notebook_hide; -} - -static void -sp_color_notebook_switch_page(GtkNotebook *notebook, - GtkWidget *page, - guint page_num, - SPColorNotebook *colorbook) -{ - if ( colorbook ) - { - ColorNotebook* nb = dynamic_cast<ColorNotebook*>(SP_COLOR_SELECTOR(colorbook)->base); - nb->switchPage( notebook, page, page_num ); - - // remember the page we switched to - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->setInt("/colorselector/page", page_num); - } -} - -void ColorNotebook::switchPage(GtkNotebook*, - GtkWidget*, - guint page_num) -{ - SPColorSelector* csel; - GtkWidget* widget; - - if ( gtk_notebook_get_current_page (GTK_NOTEBOOK (_book)) >= 0 ) - { - csel = getCurrentSelector(); - csel->base->getColorAlpha(_color, _alpha); - } - widget = gtk_notebook_get_nth_page (GTK_NOTEBOOK (_book), page_num); - if ( widget && SP_IS_COLOR_SELECTOR(widget) ) - { - csel = SP_COLOR_SELECTOR (widget); - csel->base->setColorAlpha( _color, _alpha ); - - // Temporary workaround to undo a spurious GRABBED - _released(); - } -} - -static gint sp_color_notebook_menu_handler( GtkWidget *widget, GdkEvent *event ) -{ - if (event->type == GDK_BUTTON_PRESS) - { - SPColorSelector* csel = SP_COLOR_SELECTOR(widget); - (dynamic_cast<ColorNotebook*>(csel->base))->menuHandler( event ); - - /* Tell calling code that we have handled this event; the buck - * stops here. */ - return TRUE; - } - - /* Tell calling code that we have not handled this event; pass it on. */ - return FALSE; -} - -gint ColorNotebook::menuHandler( GdkEvent* event ) -{ - GdkEventButton *bevent = (GdkEventButton *) event; - gtk_menu_popup (GTK_MENU( _popup ), NULL, NULL, NULL, NULL, - bevent->button, bevent->time); - return TRUE; -} - -static void sp_color_notebook_menuitem_response (GtkMenuItem *menuitem, gpointer user_data) -{ - gboolean active = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menuitem)); - SPColorNotebookTracker *entry = reinterpret_cast< SPColorNotebookTracker* > (user_data); - if ( entry ) - { - if ( active ) - { - (dynamic_cast<ColorNotebook*>(SP_COLOR_SELECTOR(entry->backPointer)->base))->addPage(entry->type, entry->submode); - } - else - { - (dynamic_cast<ColorNotebook*>(SP_COLOR_SELECTOR(entry->backPointer)->base))->removePage(entry->type, entry->submode); - } - } -} - -static void -sp_color_notebook_init (SPColorNotebook *colorbook) -{ - SP_COLOR_SELECTOR(colorbook)->base = new ColorNotebook( SP_COLOR_SELECTOR(colorbook) ); - - if ( SP_COLOR_SELECTOR(colorbook)->base ) - { - SP_COLOR_SELECTOR(colorbook)->base->init(); - } -} - -void ColorNotebook::init() -{ - guint row = 0; - guint i = 0; - guint j = 0; - GType *selector_types = 0; - guint selector_type_count = 0; - - /* tempory hardcoding to get types loaded */ - SP_TYPE_COLOR_SCALES; - SP_TYPE_COLOR_WHEEL_SELECTOR; -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - SP_TYPE_COLOR_ICC_SELECTOR; -#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - - /* REJON: Comment out the next line to not use the normal GTK Color - wheel. */ - -// SP_TYPE_COLOR_GTKSELECTOR; - - _updating = FALSE; - _updatingrgba = FALSE; - _btn = 0; - _popup = 0; - _trackerList = g_ptr_array_new (); - - _book = gtk_notebook_new (); - gtk_widget_show (_book); - - // Dont show the notebook tabs, use radiobuttons instead - gtk_notebook_set_show_border (GTK_NOTEBOOK (_book), false); - gtk_notebook_set_show_tabs (GTK_NOTEBOOK (_book), false); - - selector_types = g_type_children (SP_TYPE_COLOR_SELECTOR, &selector_type_count); - - for ( i = 0; i < selector_type_count; i++ ) - { - if (!g_type_is_a (selector_types[i], SP_TYPE_COLOR_NOTEBOOK)) - { - guint howmany = 1; - gpointer klass = g_type_class_ref (selector_types[i]); - if ( klass && SP_IS_COLOR_SELECTOR_CLASS(klass) ) - { - SPColorSelectorClass *ck = SP_COLOR_SELECTOR_CLASS (klass); - howmany = MAX (1, ck->submode_count); - for ( j = 0; j < howmany; j++ ) - { - SPColorNotebookTracker *entry = reinterpret_cast< SPColorNotebookTracker* > (malloc(sizeof(SPColorNotebookTracker))); - if ( entry ) - { - memset( entry, 0, sizeof(SPColorNotebookTracker) ); - entry->name = ck->name[j]; - entry->type = selector_types[i]; - entry->submode = j; - entry->enabledFull = TRUE; - entry->enabledBrief = TRUE; - entry->backPointer = SP_COLOR_NOTEBOOK(_csel); - - g_ptr_array_add (_trackerList, entry); - } - } - } - } - } - -#if GTK_CHECK_VERSION(3,0,0) - _buttonbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2); - gtk_box_set_homogeneous(GTK_BOX(_buttonbox), TRUE); -#else - _buttonbox = gtk_hbox_new (TRUE, 2); -#endif - - gtk_widget_show (_buttonbox); - _buttons = new GtkWidget *[_trackerList->len]; - - for ( i = 0; i < _trackerList->len; i++ ) - { - SPColorNotebookTracker *entry = - reinterpret_cast< SPColorNotebookTracker* > (g_ptr_array_index (_trackerList, i)); - if ( entry ) - { - addPage(entry->type, entry->submode); - } - } - -#if GTK_CHECK_VERSION(3,0,0) - GtkWidget* table = gtk_grid_new(); -#else - GtkWidget* table = gtk_table_new(2, 3, FALSE); -#endif - - gtk_widget_show (table); - - gtk_box_pack_start (GTK_BOX (_csel), table, TRUE, TRUE, 0); - - sp_set_font_size_smaller (_buttonbox); - -#if GTK_CHECK_VERSION(3,0,0) - #if GTK_CHECK_VERSION(3,12,0) - gtk_widget_set_margin_start(_buttonbox, XPAD); - gtk_widget_set_margin_end(_buttonbox, XPAD); - #else - gtk_widget_set_margin_left(_buttonbox, XPAD); - gtk_widget_set_margin_right(_buttonbox, XPAD); - #endif - gtk_widget_set_margin_top(_buttonbox, YPAD); - gtk_widget_set_margin_bottom(_buttonbox, YPAD); - gtk_widget_set_hexpand(_buttonbox, TRUE); - gtk_widget_set_valign(_buttonbox, GTK_ALIGN_CENTER); - gtk_grid_attach(GTK_GRID(table), _buttonbox, 0, row, 2, 1); -#else - gtk_table_attach (GTK_TABLE (table), _buttonbox, 0, 2, row, row + 1, - static_cast<GtkAttachOptions>(GTK_EXPAND|GTK_FILL), - static_cast<GtkAttachOptions>(0), - XPAD, YPAD); -#endif - - row++; - -#if GTK_CHECK_VERSION(3,0,0) - #if GTK_CHECK_VERSION(3,12,0) - gtk_widget_set_margin_start(_book, XPAD*2); - gtk_widget_set_margin_end(_book, XPAD*2); - #else - gtk_widget_set_margin_left(_book, XPAD*2); - gtk_widget_set_margin_right(_book, XPAD*2); - #endif - gtk_widget_set_margin_top(_book, YPAD); - gtk_widget_set_margin_bottom(_book, YPAD); - gtk_widget_set_hexpand(_book, TRUE); - gtk_widget_set_vexpand(_book, TRUE); - gtk_grid_attach(GTK_GRID(table), _book, 0, row, 2, 1); -#else - gtk_table_attach (GTK_TABLE (table), _book, 0, 2, row, row + 1, - static_cast<GtkAttachOptions>(GTK_EXPAND|GTK_FILL), - static_cast<GtkAttachOptions>(GTK_EXPAND|GTK_FILL), - XPAD*2, YPAD); -#endif - - // restore the last active page - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - _setCurrentPage(prefs->getInt("/colorselector/page", 0)); - - { - gboolean found = FALSE; - - _popup = gtk_menu_new(); - GtkMenu *menu = GTK_MENU (_popup); - - for ( i = 0; i < _trackerList->len; i++ ) - { - SPColorNotebookTracker *entry = reinterpret_cast< SPColorNotebookTracker* > (g_ptr_array_index (_trackerList, i)); - if ( entry ) - { - GtkWidget *item = gtk_check_menu_item_new_with_label (_(entry->name)); - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), entry->enabledFull); - gtk_widget_show (item); - gtk_menu_shell_append (GTK_MENU_SHELL(menu), item); - - g_signal_connect (G_OBJECT (item), "activate", - G_CALLBACK (sp_color_notebook_menuitem_response), - reinterpret_cast< gpointer > (entry) ); - found = TRUE; - } - } - - GtkWidget *arrow = gtk_arrow_new(GTK_ARROW_RIGHT, GTK_SHADOW_NONE); - gtk_widget_show (arrow); - - _btn = gtk_button_new (); - gtk_widget_show (_btn); - gtk_container_add (GTK_CONTAINER (_btn), arrow); - - GtkWidget *align = gtk_alignment_new (1.0, 0.0, 0.0, 0.0); - gtk_widget_show (align); - gtk_container_add (GTK_CONTAINER (align), _btn); - - // uncomment to reenable the "show/hide modes" menu, - // but first fix it so it remembers its settings in prefs and does not take that much space (entire vertical column!) - //gtk_table_attach (GTK_TABLE (table), align, 2, 3, row, row + 1, GTK_FILL, GTK_FILL, XPAD, YPAD); - - g_signal_connect_swapped(G_OBJECT(_btn), "event", G_CALLBACK (sp_color_notebook_menu_handler), G_OBJECT(_csel)); - if ( !found ) - { - gtk_widget_set_sensitive (_btn, FALSE); - } - } - - row++; - -#if GTK_CHECK_VERSION(3,0,0) - GtkWidget *rgbabox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); -#else - GtkWidget *rgbabox = gtk_hbox_new (FALSE, 0); -#endif - -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - /* Create color management icons */ - _box_colormanaged = gtk_event_box_new (); - GtkWidget *colormanaged = gtk_image_new_from_icon_name ("color-management-icon", GTK_ICON_SIZE_SMALL_TOOLBAR); - gtk_container_add (GTK_CONTAINER (_box_colormanaged), colormanaged); - gtk_widget_set_tooltip_text (_box_colormanaged, _("Color Managed")); - gtk_widget_set_sensitive (_box_colormanaged, false); - gtk_box_pack_start(GTK_BOX(rgbabox), _box_colormanaged, FALSE, FALSE, 2); - - _box_outofgamut = gtk_event_box_new (); - GtkWidget *outofgamut = gtk_image_new_from_icon_name ("out-of-gamut-icon", GTK_ICON_SIZE_SMALL_TOOLBAR); - gtk_container_add (GTK_CONTAINER (_box_outofgamut), outofgamut); - gtk_widget_set_tooltip_text (_box_outofgamut, _("Out of gamut!")); - gtk_widget_set_sensitive (_box_outofgamut, false); - gtk_box_pack_start(GTK_BOX(rgbabox), _box_outofgamut, FALSE, FALSE, 2); - - _box_toomuchink = gtk_event_box_new (); - GtkWidget *toomuchink = gtk_image_new_from_icon_name ("too-much-ink-icon", GTK_ICON_SIZE_SMALL_TOOLBAR); - gtk_container_add (GTK_CONTAINER (_box_toomuchink), toomuchink); - gtk_widget_set_tooltip_text (_box_toomuchink, _("Too much ink!")); - gtk_widget_set_sensitive (_box_toomuchink, false); - gtk_box_pack_start(GTK_BOX(rgbabox), _box_toomuchink, FALSE, FALSE, 2); -#endif //defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - - - /* Color picker */ - GtkWidget *picker = gtk_image_new_from_icon_name ("color-picker", GTK_ICON_SIZE_SMALL_TOOLBAR); - _btn_picker = gtk_button_new (); - gtk_button_set_relief(GTK_BUTTON(_btn_picker), GTK_RELIEF_NONE); - gtk_widget_show (_btn); - gtk_container_add (GTK_CONTAINER (_btn_picker), picker); - gtk_widget_set_tooltip_text (_btn_picker, _("Pick colors from image")); - gtk_box_pack_start(GTK_BOX(rgbabox), _btn_picker, FALSE, FALSE, 2); - g_signal_connect(G_OBJECT(_btn_picker), "clicked", G_CALLBACK(ColorNotebook::_picker_clicked), _csel); - - /* Create RGBA entry and color preview */ - _rgbal = gtk_label_new_with_mnemonic (_("RGBA_:")); - gtk_misc_set_alignment (GTK_MISC (_rgbal), 1.0, 0.5); - gtk_box_pack_start(GTK_BOX(rgbabox), _rgbal, TRUE, TRUE, 2); - - _rgbae = gtk_entry_new (); - sp_dialog_defocus_on_enter (_rgbae); - gtk_entry_set_max_length (GTK_ENTRY (_rgbae), 8); - gtk_entry_set_width_chars (GTK_ENTRY (_rgbae), 8); - gtk_widget_set_tooltip_text (_rgbae, _("Hexadecimal RGBA value of the color")); - gtk_box_pack_start(GTK_BOX(rgbabox), _rgbae, FALSE, FALSE, 0); - gtk_label_set_mnemonic_widget (GTK_LABEL(_rgbal), _rgbae); - - sp_set_font_size_smaller (rgbabox); - gtk_widget_show_all (rgbabox); - -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - //the "too much ink" icon is initially hidden - gtk_widget_hide(GTK_WIDGET(_box_toomuchink)); -#endif //defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - -#if GTK_CHECK_VERSION(3,0,0) - #if GTK_CHECK_VERSION(3,12,0) - gtk_widget_set_margin_start(rgbabox, XPAD); - gtk_widget_set_margin_end(rgbabox, XPAD); - #else - gtk_widget_set_margin_left(rgbabox, XPAD); - gtk_widget_set_margin_right(rgbabox, XPAD); - #endif - gtk_widget_set_margin_top(rgbabox, YPAD); - gtk_widget_set_margin_bottom(rgbabox, YPAD); - gtk_grid_attach(GTK_GRID(table), rgbabox, 0, row, 2, 1); -#else - gtk_table_attach (GTK_TABLE (table), rgbabox, 0, 2, row, row + 1, GTK_FILL, GTK_SHRINK, XPAD, YPAD); -#endif - -#ifdef SPCS_PREVIEW - _p = sp_color_preview_new (0xffffffff); - gtk_widget_show (_p); - gtk_table_attach (GTK_TABLE (table), _p, 2, 3, row, row + 1, GTK_FILL, GTK_FILL, XPAD, YPAD); -#endif - - _switchId = g_signal_connect(G_OBJECT (_book), "switch-page", - G_CALLBACK (sp_color_notebook_switch_page), SP_COLOR_NOTEBOOK(_csel)); - - _entryId = g_signal_connect (G_OBJECT (_rgbae), "changed", G_CALLBACK (ColorNotebook::_rgbaEntryChangedHook), _csel); -} - -static void sp_color_notebook_dispose(GObject *object) -{ - if (G_OBJECT_CLASS(sp_color_notebook_parent_class)->dispose) - G_OBJECT_CLASS(sp_color_notebook_parent_class)->dispose(object); -} - -ColorNotebook::~ColorNotebook() -{ - if ( _trackerList ) - { - g_ptr_array_free (_trackerList, TRUE); - _trackerList = 0; - } - - if ( _switchId ) - { - if ( _book ) - { - g_signal_handler_disconnect (_book, _switchId); - _switchId = 0; - } - } - - if ( _buttons ) - { - delete [] _buttons; - _buttons = 0; - } - -} - -static void -sp_color_notebook_show_all (GtkWidget *widget) -{ - gtk_widget_show (widget); -} - -static void sp_color_notebook_hide(GtkWidget *widget) -{ - gtk_widget_hide(widget); -} - -GtkWidget *sp_color_notebook_new() -{ - SPColorNotebook *colorbook = SP_COLOR_NOTEBOOK(g_object_new (SP_TYPE_COLOR_NOTEBOOK, NULL)); - - return GTK_WIDGET(colorbook); -} - -ColorNotebook::ColorNotebook( SPColorSelector* csel ) - : ColorSelector( csel ) -{ -} - -SPColorSelector* ColorNotebook::getCurrentSelector() -{ - SPColorSelector* csel = NULL; - gint current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (_book)); - - if ( current_page >= 0 ) - { - GtkWidget* widget = gtk_notebook_get_nth_page (GTK_NOTEBOOK (_book), current_page); - if ( SP_IS_COLOR_SELECTOR (widget) ) - { - csel = SP_COLOR_SELECTOR (widget); - } - } - - return csel; -} - -void ColorNotebook::_colorChanged() -{ - SPColorSelector* cselPage = getCurrentSelector(); - if ( cselPage ) - { - cselPage->base->setColorAlpha( _color, _alpha ); - } - - _updateRgbaEntry( _color, _alpha ); -} - -void ColorNotebook::_picker_clicked(GtkWidget * /*widget*/, SPColorNotebook * /*colorbook*/) -{ - // Set the dropper into a "one click" mode, so it reverts to the previous tool after a click - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->setBool("/tools/dropper/onetimepick", true); - Inkscape::UI::Tools::sp_toggle_dropper(SP_ACTIVE_DESKTOP); -} - -void ColorNotebook::_rgbaEntryChangedHook(GtkEntry *entry, SPColorNotebook *colorbook) -{ - (dynamic_cast<ColorNotebook*>(SP_COLOR_SELECTOR(colorbook)->base))->_rgbaEntryChanged( entry ); -} - -void ColorNotebook::_rgbaEntryChanged(GtkEntry* entry) -{ - if (_updating) return; - if (_updatingrgba) return; - - const gchar *t = gtk_entry_get_text( entry ); - - if (t) { - Glib::ustring text = t; - bool changed = false; - if (!text.empty() && text[0] == '#') { - changed = true; - text.erase(0,1); - if (text.size() == 6) { - // it was a standard RGB hex - unsigned int alph = SP_COLOR_F_TO_U(_alpha); - gchar* tmp = g_strdup_printf("%02x", alph); - text += tmp; - g_free(tmp); - } - } - gchar* str = g_strdup(text.c_str()); - gchar* end = 0; - guint64 rgba = g_ascii_strtoull( str, &end, 16 ); - if ( end != str ) { - ptrdiff_t len = end - str; - if ( len < 8 ) { - rgba = rgba << ( 4 * ( 8 - len ) ); - } - _updatingrgba = TRUE; - if ( changed ) { - gtk_entry_set_text( entry, str ); - } - SPColor color( rgba ); - setColorAlpha( color, SP_RGBA32_A_F(rgba), true ); - _updatingrgba = FALSE; - } - g_free(str); - } -} - -// TODO pass in param so as to avoid the need for SP_ACTIVE_DOCUMENT -void ColorNotebook::_updateRgbaEntry( const SPColor& color, gfloat alpha ) -{ - g_return_if_fail( ( 0.0 <= alpha ) && ( alpha <= 1.0 ) ); - -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - /* update color management icon*/ - gtk_widget_set_sensitive (_box_colormanaged, color.icc != NULL); - - /* update out-of-gamut icon */ - gtk_widget_set_sensitive (_box_outofgamut, false); - if (color.icc){ - Inkscape::ColorProfile* target_profile = SP_ACTIVE_DOCUMENT->profileManager->find(color.icc->colorProfile.c_str()); - if ( target_profile ) - gtk_widget_set_sensitive(_box_outofgamut, target_profile->GamutCheck(color)); - } - - /* update too-much-ink icon */ - gtk_widget_set_sensitive (_box_toomuchink, false); - if (color.icc){ - Inkscape::ColorProfile* prof = SP_ACTIVE_DOCUMENT->profileManager->find(color.icc->colorProfile.c_str()); - if ( prof && CMSSystem::isPrintColorSpace(prof) ) { - gtk_widget_show(GTK_WIDGET(_box_toomuchink)); - double ink_sum = 0; - for (unsigned int i=0; i<color.icc->colors.size(); i++){ - ink_sum += color.icc->colors[i]; - } - - /* Some literature states that when the sum of paint values exceed 320%, it is considered to be a satured color, - which means the paper can get too wet due to an excessive ammount of ink. This may lead to several issues - such as misalignment and poor quality of printing in general.*/ - if ( ink_sum > 3.2 ) - gtk_widget_set_sensitive (_box_toomuchink, true); - } else { - gtk_widget_hide(GTK_WIDGET(_box_toomuchink)); - } - } -#endif //defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - - if ( !_updatingrgba ) - { - gchar s[32]; - guint32 rgba; - - /* Update RGBA entry */ - rgba = color.toRGBA32( alpha ); - - g_snprintf (s, 32, "%08x", rgba); - const gchar* oldText = gtk_entry_get_text( GTK_ENTRY( _rgbae ) ); - if ( strcmp( oldText, s ) != 0 ) - { - g_signal_handler_block( _rgbae, _entryId ); - gtk_entry_set_text( GTK_ENTRY(_rgbae), s ); - g_signal_handler_unblock( _rgbae, _entryId ); - } - } -} - -void ColorNotebook::_setCurrentPage(int i) -{ - gtk_notebook_set_current_page(GTK_NOTEBOOK(_book), i); - - if (_buttons && _trackerList && (static_cast<size_t>(i) < _trackerList->len) ) { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(_buttons[i]), TRUE); - } -} - -void ColorNotebook::_buttonClicked(GtkWidget *widget, SPColorNotebook *colorbook) -{ - ColorNotebook* nb = dynamic_cast<ColorNotebook*>(SP_COLOR_SELECTOR(colorbook)->base); - - if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(widget))) { - return; - } - - for(gint i = 0; i < gtk_notebook_get_n_pages (GTK_NOTEBOOK (nb->_book)); i++) { - if (nb->_buttons[i] == widget) { - gtk_notebook_set_current_page (GTK_NOTEBOOK (nb->_book), i); - } - } -} - -void ColorNotebook::_entryGrabbed (SPColorSelector *, SPColorNotebook *colorbook) -{ - ColorNotebook* nb = dynamic_cast<ColorNotebook*>(SP_COLOR_SELECTOR(colorbook)->base); - nb->_grabbed(); -} - -void ColorNotebook::_entryDragged (SPColorSelector *csel, SPColorNotebook *colorbook) -{ - gboolean oldState; - ColorNotebook* nb = dynamic_cast<ColorNotebook*>(SP_COLOR_SELECTOR(colorbook)->base); - - oldState = nb->_dragging; - - nb->_dragging = TRUE; - nb->_entryModified( csel, colorbook ); - - nb->_dragging = oldState; -} - -void ColorNotebook::_entryReleased (SPColorSelector *, SPColorNotebook *colorbook) -{ - ColorNotebook* nb = dynamic_cast<ColorNotebook*>(SP_COLOR_SELECTOR(colorbook)->base); - nb->_released(); -} - -void ColorNotebook::_entryChanged (SPColorSelector *csel, SPColorNotebook *colorbook) -{ - gboolean oldState; - ColorNotebook* nb = dynamic_cast<ColorNotebook*>(SP_COLOR_SELECTOR(colorbook)->base); - - oldState = nb->_dragging; - - nb->_dragging = FALSE; - nb->_entryModified( csel, colorbook ); - - nb->_dragging = oldState; -} - -void ColorNotebook::_entryModified (SPColorSelector *csel, SPColorNotebook *colorbook) -{ - g_return_if_fail (colorbook != NULL); - g_return_if_fail (SP_IS_COLOR_NOTEBOOK (colorbook)); - g_return_if_fail (csel != NULL); - g_return_if_fail (SP_IS_COLOR_SELECTOR (csel)); - - ColorNotebook* nb = dynamic_cast<ColorNotebook*>(SP_COLOR_SELECTOR(colorbook)->base); - SPColor color; - gfloat alpha = 1.0; - - csel->base->getColorAlpha( color, alpha ); - nb->_updateRgbaEntry( color, alpha ); - nb->_updateInternals( color, alpha, nb->_dragging ); -} - -GtkWidget* ColorNotebook::addPage(GType page_type, guint submode) -{ - GtkWidget *page; - - page = sp_color_selector_new( page_type ); - if ( page ) - { - GtkWidget* tab_label = 0; - SPColorSelector* csel; - - csel = SP_COLOR_SELECTOR (page); - if ( submode > 0 ) - { - csel->base->setSubmode( submode ); - } - gtk_widget_show (page); - int index = csel->base ? csel->base->getSubmode() : 0; - const gchar* str = _(SP_COLOR_SELECTOR_GET_CLASS (csel)->name[index]); -// g_message( "Hitting up for tab for '%s'", str ); - tab_label = gtk_label_new(_(str)); - gint pageNum = gtk_notebook_append_page( GTK_NOTEBOOK (_book), page, tab_label ); - - // Add a button for each page - _buttons[pageNum] = gtk_radio_button_new_with_label(NULL, _(str)); - gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(_buttons[pageNum]), FALSE); - if (pageNum > 0) { - GSList *group = gtk_radio_button_get_group (GTK_RADIO_BUTTON(_buttons[0])); - gtk_radio_button_set_group (GTK_RADIO_BUTTON(_buttons[pageNum]), group); - } - gtk_widget_show (_buttons[pageNum]); - gtk_box_pack_start (GTK_BOX (_buttonbox), _buttons[pageNum], TRUE, TRUE, 0); - - g_signal_connect (G_OBJECT (_buttons[pageNum]), "clicked", G_CALLBACK (_buttonClicked), _csel); - g_signal_connect (G_OBJECT (page), "grabbed", G_CALLBACK (_entryGrabbed), _csel); - g_signal_connect (G_OBJECT (page), "dragged", G_CALLBACK (_entryDragged), _csel); - g_signal_connect (G_OBJECT (page), "released", G_CALLBACK (_entryReleased), _csel); - g_signal_connect (G_OBJECT (page), "changed", G_CALLBACK (_entryChanged), _csel); - } - - return page; -} - -GtkWidget* ColorNotebook::getPage(GType page_type, guint submode) -{ - gint count = 0; - gint i = 0; - GtkWidget* page = 0; - -// count = gtk_notebook_get_n_pages (_book); - count = 200; - for ( i = 0; i < count && !page; i++ ) - { - page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (_book), i); - if ( page ) - { - SPColorSelector* csel; - guint pagemode; - csel = SP_COLOR_SELECTOR (page); - pagemode = csel->base->getSubmode(); - if ( G_TYPE_FROM_INSTANCE (page) == page_type - && pagemode == submode ) - { - // found it. - break; - } - else - { - page = 0; - } - } - else - { - break; - } - } - return page; -} - -void ColorNotebook::removePage( GType page_type, guint submode ) -{ - GtkWidget *page = 0; - - page = getPage(page_type, submode); - if ( page ) - { - gint where = gtk_notebook_page_num (GTK_NOTEBOOK (_book), page); - if ( where >= 0 ) - { - if ( gtk_notebook_get_current_page (GTK_NOTEBOOK (_book)) == where ) - { -// getColorAlpha(_color, &_alpha); - } - gtk_notebook_remove_page (GTK_NOTEBOOK (_book), where); - } - } -} - -/* - 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 : diff --git a/src/widgets/sp-color-notebook.h b/src/widgets/sp-color-notebook.h deleted file mode 100644 index 469bb56e8..000000000 --- a/src/widgets/sp-color-notebook.h +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef SEEN_SP_COLOR_NOTEBOOK_H -#define SEEN_SP_COLOR_NOTEBOOK_H - -/* - * A notebook with RGB, CMYK, CMS, HSL, and Wheel pages - * - * Author: - * Lauris Kaplinski <lauris@kaplinski.com> - * - * Copyright (C) 2001-2002 Lauris Kaplinski - * - * This code is in public domain - */ - -#include "sp-color-selector.h" - -#include <glib.h> - -struct SPColorNotebook; - -class ColorNotebook: public ColorSelector -{ -public: - ColorNotebook( SPColorSelector* csel ); - virtual ~ColorNotebook(); - - virtual void init(); - - SPColorSelector* getCurrentSelector(); - void switchPage( GtkNotebook *notebook, GtkWidget *page, guint page_num ); - - GtkWidget* addPage( GType page_type, guint submode ); - void removePage( GType page_type, guint submode ); - GtkWidget* getPage( GType page_type, guint submode ); - - gint menuHandler( GdkEvent* event ); - -protected: - static void _rgbaEntryChangedHook( GtkEntry* entry, SPColorNotebook *colorbook ); - static void _entryGrabbed( SPColorSelector *csel, SPColorNotebook *colorbook ); - static void _entryDragged( SPColorSelector *csel, SPColorNotebook *colorbook ); - static void _entryReleased( SPColorSelector *csel, SPColorNotebook *colorbook ); - static void _entryChanged( SPColorSelector *csel, SPColorNotebook *colorbook ); - static void _entryModified( SPColorSelector *csel, SPColorNotebook *colorbook ); - static void _buttonClicked(GtkWidget *widget, SPColorNotebook *colorbook); - static void _picker_clicked(GtkWidget *widget, SPColorNotebook *colorbook); - - virtual void _colorChanged(); - - void _rgbaEntryChanged( GtkEntry* entry ); - void _updateRgbaEntry( const SPColor& color, gfloat alpha ); - void _setCurrentPage(int i); - - gboolean _updating : 1; - gboolean _updatingrgba : 1; - gboolean _dragging : 1; - gulong _switchId; - gulong _entryId; - GtkWidget *_book; - GtkWidget *_buttonbox; - GtkWidget **_buttons; - GtkWidget *_rgbal, *_rgbae; /* RGBA entry */ -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - GtkWidget *_box_outofgamut, *_box_colormanaged, *_box_toomuchink; -#endif //defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - GtkWidget *_btn_picker; - GtkWidget *_p; /* Color preview */ - GtkWidget *_btn; - GtkWidget *_popup; - GPtrArray *_trackerList; - -private: - // By default, disallow copy constructor and assignment operator - ColorNotebook( const ColorNotebook& obj ); - ColorNotebook& operator=( const ColorNotebook& obj ); -}; - - - -#define SP_TYPE_COLOR_NOTEBOOK (sp_color_notebook_get_type ()) -#define SP_COLOR_NOTEBOOK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SP_TYPE_COLOR_NOTEBOOK, SPColorNotebook)) -#define SP_COLOR_NOTEBOOK_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), SP_TYPE_COLOR_NOTEBOOK, SPColorNotebookClass)) -#define SP_IS_COLOR_NOTEBOOK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SP_TYPE_COLOR_NOTEBOOK)) -#define SP_IS_COLOR_NOTEBOOK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SP_TYPE_COLOR_NOTEBOOK)) - -struct SPColorNotebook { - SPColorSelector parent; /* Parent */ -}; - -struct SPColorNotebookClass { - SPColorSelectorClass parent_class; - - void (* grabbed) (SPColorNotebook *rgbsel); - void (* dragged) (SPColorNotebook *rgbsel); - void (* released) (SPColorNotebook *rgbsel); - void (* changed) (SPColorNotebook *rgbsel); -}; - -GType sp_color_notebook_get_type(void); - -GtkWidget *sp_color_notebook_new (void); - -/* void sp_color_notebook_set_mode (SPColorNotebook *csel, SPColorNotebookMode mode); */ -/* SPColorNotebookMode sp_color_notebook_get_mode (SPColorNotebook *csel); */ - - - -#endif // SEEN_SP_COLOR_NOTEBOOK_H - -/* - 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 : - diff --git a/src/widgets/sp-color-scales.cpp b/src/widgets/sp-color-scales.cpp deleted file mode 100644 index 60ba62ec5..000000000 --- a/src/widgets/sp-color-scales.cpp +++ /dev/null @@ -1,760 +0,0 @@ -/* - * bulia byak <buliabyak@users.sf.net> - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include <math.h> -#include <gtk/gtk.h> -#include <glibmm/i18n.h> -#include "ui/dialog-events.h" -#include "sp-color-scales.h" -#include "sp-color-slider.h" -#include "svg/svg-icc-color.h" - -#define CSC_CHANNEL_R (1 << 0) -#define CSC_CHANNEL_G (1 << 1) -#define CSC_CHANNEL_B (1 << 2) -#define CSC_CHANNEL_A (1 << 3) -#define CSC_CHANNEL_H (1 << 0) -#define CSC_CHANNEL_S (1 << 1) -#define CSC_CHANNEL_V (1 << 2) -#define CSC_CHANNEL_C (1 << 0) -#define CSC_CHANNEL_M (1 << 1) -#define CSC_CHANNEL_Y (1 << 2) -#define CSC_CHANNEL_K (1 << 3) -#define CSC_CHANNEL_CMYKA (1 << 4) - -#define CSC_CHANNELS_ALL 0 - - -G_BEGIN_DECLS - -static void sp_color_scales_dispose(GObject *object); - -static void sp_color_scales_show_all (GtkWidget *widget); -static void sp_color_scales_hide(GtkWidget *widget); - -static const gchar *sp_color_scales_hue_map (void); - -G_END_DECLS - -#define XPAD 4 -#define YPAD 1 - -#define noDUMP_CHANGE_INFO 1 - -G_DEFINE_TYPE(SPColorScales, sp_color_scales, SP_TYPE_COLOR_SELECTOR); - -static void -sp_color_scales_class_init (SPColorScalesClass *klass) -{ - static const gchar* nameset[] = {N_("RGB"), N_("HSL"), N_("CMYK"), 0}; - GObjectClass *object_class = G_OBJECT_CLASS(klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); - SPColorSelectorClass *selector_class = SP_COLOR_SELECTOR_CLASS (klass); - - selector_class->name = nameset; - selector_class->submode_count = 3; - - object_class->dispose = sp_color_scales_dispose; - - widget_class->show_all = sp_color_scales_show_all; - widget_class->hide = sp_color_scales_hide; -} - -ColorScales::ColorScales( SPColorSelector* csel ) - : ColorSelector( csel ), - _mode( SP_COLOR_SCALES_MODE_NONE ), - _rangeLimit( 255.0 ), - _updating( FALSE ), - _dragging( FALSE ) -{ - for (gint i = 0; i < 5; i++) { - _l[i] = 0; - _a[i] = 0; - _s[i] = 0; - _b[i] = 0; - } -} - -ColorScales::~ColorScales() -{ - for (gint i = 0; i < 5; i++) { - _l[i] = 0; - _a[i] = 0; - _s[i] = 0; - _b[i] = 0; - } -} - -void sp_color_scales_init (SPColorScales *cs) -{ - SP_COLOR_SELECTOR(cs)->base = new ColorScales( SP_COLOR_SELECTOR(cs) ); - - if ( SP_COLOR_SELECTOR(cs)->base ) - { - SP_COLOR_SELECTOR(cs)->base->init(); - } -} - -void ColorScales::init() -{ - gint i; - - _updating = FALSE; - _dragging = FALSE; - -#if GTK_CHECK_VERSION(3,0,0) - GtkWidget *t = gtk_grid_new(); -#else - GtkWidget *t = gtk_table_new (5, 3, FALSE); -#endif - gtk_widget_show (t); - gtk_box_pack_start (GTK_BOX (_csel), t, TRUE, TRUE, 4); - - /* Create components */ - for (i = 0; i < static_cast< gint > (G_N_ELEMENTS(_a)) ; i++) { - /* Label */ - _l[i] = gtk_label_new(""); - gtk_misc_set_alignment (GTK_MISC (_l[i]), 1.0, 0.5); - gtk_widget_show (_l[i]); - -#if GTK_CHECK_VERSION(3,0,0) - #if GTK_CHECK_VERSION(3,12,0) - gtk_widget_set_margin_start(_l[i], XPAD); - gtk_widget_set_margin_end(_l[i], XPAD); - #else - gtk_widget_set_margin_left(_l[i], XPAD); - gtk_widget_set_margin_right(_l[i], XPAD); - #endif - gtk_widget_set_margin_top(_l[i], YPAD); - gtk_widget_set_margin_bottom(_l[i], YPAD); - gtk_grid_attach(GTK_GRID(t), _l[i], 0, i, 1, 1); -#else - gtk_table_attach (GTK_TABLE (t), _l[i], 0, 1, i, i + 1, GTK_FILL, GTK_FILL, XPAD, YPAD); -#endif - - /* Adjustment */ - _a[i] = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, _rangeLimit, 1.0, 10.0, 10.0)); - /* Slider */ - _s[i] = sp_color_slider_new (_a[i]); - gtk_widget_show (_s[i]); - -#if GTK_CHECK_VERSION(3,0,0) - #if GTK_CHECK_VERSION(3,12,0) - gtk_widget_set_margin_start(_s[i], XPAD); - gtk_widget_set_margin_end(_s[i], XPAD); - #else - gtk_widget_set_margin_left(_s[i], XPAD); - gtk_widget_set_margin_right(_s[i], XPAD); - #endif - gtk_widget_set_margin_top(_s[i], YPAD); - gtk_widget_set_margin_bottom(_s[i], YPAD); - gtk_widget_set_hexpand(_s[i], TRUE); - gtk_grid_attach(GTK_GRID(t), _s[i], 1, i, 1, 1); -#else - gtk_table_attach (GTK_TABLE (t), _s[i], 1, 2, i, i + 1, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), GTK_FILL, XPAD, YPAD); -#endif - - /* Spinbutton */ - _b[i] = gtk_spin_button_new (GTK_ADJUSTMENT (_a[i]), 1.0, 0); - sp_dialog_defocus_on_enter (_b[i]); - gtk_label_set_mnemonic_widget (GTK_LABEL(_l[i]), _b[i]); - gtk_widget_show (_b[i]); - -#if GTK_CHECK_VERSION(3,0,0) - #if GTK_CHECK_VERSION(3,12,0) - gtk_widget_set_margin_start(_b[i], XPAD); - gtk_widget_set_margin_end(_b[i], XPAD); - #else - gtk_widget_set_margin_left(_b[i], XPAD); - gtk_widget_set_margin_right(_b[i], XPAD); - #endif - gtk_widget_set_margin_top(_b[i], YPAD); - gtk_widget_set_margin_bottom(_b[i], YPAD); - gtk_widget_set_halign(_b[i], GTK_ALIGN_CENTER); - gtk_widget_set_valign(_b[i], GTK_ALIGN_CENTER); - gtk_grid_attach(GTK_GRID(t), _b[i], 2, i, 1, 1); -#else - gtk_table_attach (GTK_TABLE (t), _b[i], 2, 3, i, i + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, XPAD, YPAD); -#endif - - /* Attach channel value to adjustment */ - g_object_set_data (G_OBJECT (_a[i]), "channel", GINT_TO_POINTER (i)); - /* Signals */ - g_signal_connect (G_OBJECT (_a[i]), "value_changed", - G_CALLBACK (_adjustmentAnyChanged), _csel); - g_signal_connect (G_OBJECT (_s[i]), "grabbed", - G_CALLBACK (_sliderAnyGrabbed), _csel); - g_signal_connect (G_OBJECT (_s[i]), "released", - G_CALLBACK (_sliderAnyReleased), _csel); - g_signal_connect (G_OBJECT (_s[i]), "changed", - G_CALLBACK (_sliderAnyChanged), _csel); - } - - /* Initial mode is none, so it works */ - setMode(SP_COLOR_SCALES_MODE_RGB); -} - -static void sp_color_scales_dispose(GObject *object) -{ - if (G_OBJECT_CLASS(sp_color_scales_parent_class)->dispose) - G_OBJECT_CLASS(sp_color_scales_parent_class)->dispose(object); -} - -static void -sp_color_scales_show_all (GtkWidget *widget) -{ - gtk_widget_show (widget); -} - -static void sp_color_scales_hide(GtkWidget *widget) -{ - gtk_widget_hide(widget); -} - -GtkWidget *sp_color_scales_new() -{ - SPColorScales *csel = SP_COLOR_SCALES(g_object_new (SP_TYPE_COLOR_SCALES, NULL)); - - return GTK_WIDGET (csel); -} - -void ColorScales::_recalcColor( gboolean changing ) -{ - if ( changing ) - { - SPColor color; - gfloat alpha = 1.0; - gfloat c[5]; - - switch (_mode) { - case SP_COLOR_SCALES_MODE_RGB: - case SP_COLOR_SCALES_MODE_HSV: - _getRgbaFloatv(c); - color.set( c[0], c[1], c[2] ); - alpha = c[3]; - break; - case SP_COLOR_SCALES_MODE_CMYK: - { - _getCmykaFloatv( c ); - - float rgb[3]; - sp_color_cmyk_to_rgb_floatv( rgb, c[0], c[1], c[2], c[3] ); - color.set( rgb[0], rgb[1], rgb[2] ); - alpha = c[4]; - break; - } - default: - g_warning ("file %s: line %d: Illegal color selector mode %d", __FILE__, __LINE__, _mode); - break; - } - - /* Preserve ICC */ - color.icc = _color.icc ? new SVGICCColor(*_color.icc) : 0; - - _updateInternals( color, alpha, _dragging ); - } - else - { - _updateInternals( _color, _alpha, _dragging ); - } -} - -/* Helpers for setting color value */ -gfloat ColorScales::getScaled( const GtkAdjustment *a ) -{ - gfloat val = gtk_adjustment_get_value (const_cast<GtkAdjustment*>(a)) - / gtk_adjustment_get_upper (const_cast<GtkAdjustment*>(a)); - return val; -} - -void ColorScales::setScaled( GtkAdjustment *a, gfloat v ) -{ - gfloat val = v * gtk_adjustment_get_upper (a); - gtk_adjustment_set_value( a, val ); -} - -void ColorScales::_setRangeLimit( gdouble upper ) -{ - _rangeLimit = upper; - for ( gint i = 0; i < static_cast<gint>(G_N_ELEMENTS(_a)); i++ ) { - gtk_adjustment_set_upper (_a[i], upper); - gtk_adjustment_changed( _a[i] ); - } -} - -void ColorScales::_colorChanged() -{ -#ifdef DUMP_CHANGE_INFO - g_message("ColorScales::_colorChanged( this=%p, %f, %f, %f, %f)", this, _color.v.c[0], _color.v.c[1], _color.v.c[2], _alpha ); -#endif - gfloat tmp[3]; - gfloat c[5] = {0.0, 0.0, 0.0, 0.0}; - - switch (_mode) { - case SP_COLOR_SCALES_MODE_RGB: - sp_color_get_rgb_floatv( &_color, c ); - c[3] = _alpha; - c[4] = 0.0; - break; - case SP_COLOR_SCALES_MODE_HSV: - sp_color_get_rgb_floatv( &_color, tmp ); - sp_color_rgb_to_hsl_floatv (c, tmp[0], tmp[1], tmp[2]); - c[3] = _alpha; - c[4] = 0.0; - break; - case SP_COLOR_SCALES_MODE_CMYK: - sp_color_get_cmyk_floatv( &_color, c ); - c[4] = _alpha; - break; - default: - g_warning ("file %s: line %d: Illegal color selector mode %d", __FILE__, __LINE__, _mode); - break; - } - - _updating = TRUE; - setScaled( _a[0], c[0] ); - setScaled( _a[1], c[1] ); - setScaled( _a[2], c[2] ); - setScaled( _a[3], c[3] ); - setScaled( _a[4], c[4] ); - _updateSliders( CSC_CHANNELS_ALL ); - _updating = FALSE; -} - -void ColorScales::_getRgbaFloatv( gfloat *rgba ) -{ - g_return_if_fail (rgba != NULL); - - switch (_mode) { - case SP_COLOR_SCALES_MODE_RGB: - rgba[0] = getScaled(_a[0]); - rgba[1] = getScaled(_a[1]); - rgba[2] = getScaled(_a[2]); - rgba[3] = getScaled(_a[3]); - break; - case SP_COLOR_SCALES_MODE_HSV: - sp_color_hsl_to_rgb_floatv (rgba, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2])); - rgba[3] = getScaled(_a[3]); - break; - case SP_COLOR_SCALES_MODE_CMYK: - sp_color_cmyk_to_rgb_floatv (rgba, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), getScaled(_a[3])); - rgba[3] = getScaled(_a[4]); - break; - default: - g_warning ("file %s: line %d: Illegal color selector mode", __FILE__, __LINE__); - break; - } -} - -void ColorScales::_getCmykaFloatv( gfloat *cmyka ) -{ - gfloat rgb[3]; - - g_return_if_fail (cmyka != NULL); - - switch (_mode) { - case SP_COLOR_SCALES_MODE_RGB: - sp_color_rgb_to_cmyk_floatv (cmyka, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2])); - cmyka[4] = getScaled(_a[3]); - break; - case SP_COLOR_SCALES_MODE_HSV: - sp_color_hsl_to_rgb_floatv (rgb, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2])); - sp_color_rgb_to_cmyk_floatv (cmyka, rgb[0], rgb[1], rgb[2]); - cmyka[4] = getScaled(_a[3]); - break; - case SP_COLOR_SCALES_MODE_CMYK: - cmyka[0] = getScaled(_a[0]); - cmyka[1] = getScaled(_a[1]); - cmyka[2] = getScaled(_a[2]); - cmyka[3] = getScaled(_a[3]); - cmyka[4] = getScaled(_a[4]); - break; - default: - g_warning ("file %s: line %d: Illegal color selector mode", __FILE__, __LINE__); - break; - } -} - -guint32 ColorScales::_getRgba32() -{ - gfloat c[4]; - guint32 rgba; - - _getRgbaFloatv(c); - - rgba = SP_RGBA32_F_COMPOSE (c[0], c[1], c[2], c[3]); - - return rgba; -} - -void ColorScales::setMode(SPColorScalesMode mode) -{ - gfloat rgba[4]; - gfloat c[4]; - - if (_mode == mode) return; - - if ((_mode == SP_COLOR_SCALES_MODE_RGB) || - (_mode == SP_COLOR_SCALES_MODE_HSV) || - (_mode == SP_COLOR_SCALES_MODE_CMYK)) { - _getRgbaFloatv(rgba); - } else { - rgba[0] = rgba[1] = rgba[2] = rgba[3] = 1.0; - } - - _mode = mode; - - switch (mode) { - case SP_COLOR_SCALES_MODE_RGB: - _setRangeLimit(255.0); - gtk_label_set_markup_with_mnemonic (GTK_LABEL (_l[0]), _("_R:")); - gtk_widget_set_tooltip_text (_s[0], _("Red")); - gtk_widget_set_tooltip_text (_b[0], _("Red")); - gtk_label_set_markup_with_mnemonic (GTK_LABEL (_l[1]), _("_G:")); - gtk_widget_set_tooltip_text (_s[1], _("Green")); - gtk_widget_set_tooltip_text (_b[1], _("Green")); - gtk_label_set_markup_with_mnemonic (GTK_LABEL (_l[2]), _("_B:")); - gtk_widget_set_tooltip_text (_s[2], _("Blue")); - gtk_widget_set_tooltip_text (_b[2], _("Blue")); - gtk_label_set_markup_with_mnemonic (GTK_LABEL (_l[3]), _("_A:")); - gtk_widget_set_tooltip_text (_s[3], _("Alpha (opacity)")); - gtk_widget_set_tooltip_text (_b[3], _("Alpha (opacity)")); - sp_color_slider_set_map (SP_COLOR_SLIDER (_s[0]), NULL); - gtk_widget_hide (_l[4]); - gtk_widget_hide (_s[4]); - gtk_widget_hide (_b[4]); - _updating = TRUE; - setScaled( _a[0], rgba[0] ); - setScaled( _a[1], rgba[1] ); - setScaled( _a[2], rgba[2] ); - setScaled( _a[3], rgba[3] ); - _updating = FALSE; - _updateSliders( CSC_CHANNELS_ALL ); - break; - case SP_COLOR_SCALES_MODE_HSV: - _setRangeLimit(255.0); - gtk_label_set_markup_with_mnemonic (GTK_LABEL (_l[0]), _("_H:")); - gtk_widget_set_tooltip_text (_s[0], _("Hue")); - gtk_widget_set_tooltip_text (_b[0], _("Hue")); - gtk_label_set_markup_with_mnemonic (GTK_LABEL (_l[1]), _("_S:")); - gtk_widget_set_tooltip_text (_s[1], _("Saturation")); - gtk_widget_set_tooltip_text (_b[1], _("Saturation")); - gtk_label_set_markup_with_mnemonic (GTK_LABEL (_l[2]), _("_L:")); - gtk_widget_set_tooltip_text (_s[2], _("Lightness")); - gtk_widget_set_tooltip_text (_b[2], _("Lightness")); - gtk_label_set_markup_with_mnemonic (GTK_LABEL (_l[3]), _("_A:")); - gtk_widget_set_tooltip_text (_s[3], _("Alpha (opacity)")); - gtk_widget_set_tooltip_text (_b[3], _("Alpha (opacity)")); - sp_color_slider_set_map (SP_COLOR_SLIDER (_s[0]), (guchar *)(sp_color_scales_hue_map())); - gtk_widget_hide (_l[4]); - gtk_widget_hide (_s[4]); - gtk_widget_hide (_b[4]); - _updating = TRUE; - c[0] = 0.0; - sp_color_rgb_to_hsl_floatv (c, rgba[0], rgba[1], rgba[2]); - setScaled( _a[0], c[0] ); - setScaled( _a[1], c[1] ); - setScaled( _a[2], c[2] ); - setScaled( _a[3], rgba[3] ); - _updating = FALSE; - _updateSliders( CSC_CHANNELS_ALL ); - break; - case SP_COLOR_SCALES_MODE_CMYK: - _setRangeLimit(100.0); - gtk_label_set_markup_with_mnemonic (GTK_LABEL (_l[0]), _("_C:")); - gtk_widget_set_tooltip_text (_s[0], _("Cyan")); - gtk_widget_set_tooltip_text (_b[0], _("Cyan")); - gtk_label_set_markup_with_mnemonic (GTK_LABEL (_l[1]), _("_M:")); - gtk_widget_set_tooltip_text (_s[1], _("Magenta")); - gtk_widget_set_tooltip_text (_b[1], _("Magenta")); - gtk_label_set_markup_with_mnemonic (GTK_LABEL (_l[2]), _("_Y:")); - gtk_widget_set_tooltip_text (_s[2], _("Yellow")); - gtk_widget_set_tooltip_text (_b[2], _("Yellow")); - gtk_label_set_markup_with_mnemonic (GTK_LABEL (_l[3]), _("_K:")); - gtk_widget_set_tooltip_text (_s[3], _("Black")); - gtk_widget_set_tooltip_text (_b[3], _("Black")); - gtk_label_set_markup_with_mnemonic (GTK_LABEL (_l[4]), _("_A:")); - gtk_widget_set_tooltip_text (_s[4], _("Alpha (opacity)")); - gtk_widget_set_tooltip_text (_b[4], _("Alpha (opacity)")); - sp_color_slider_set_map (SP_COLOR_SLIDER (_s[0]), NULL); - gtk_widget_show (_l[4]); - gtk_widget_show (_s[4]); - gtk_widget_show (_b[4]); - _updating = TRUE; - - sp_color_rgb_to_cmyk_floatv (c, rgba[0], rgba[1], rgba[2]); - setScaled( _a[0], c[0] ); - setScaled( _a[1], c[1] ); - setScaled( _a[2], c[2] ); - setScaled( _a[3], c[3] ); - - setScaled( _a[4], rgba[3] ); - _updating = FALSE; - _updateSliders( CSC_CHANNELS_ALL ); - break; - default: - g_warning ("file %s: line %d: Illegal color selector mode", __FILE__, __LINE__); - break; - } -} - -SPColorScalesMode ColorScales::getMode() const -{ - return _mode; -} - -void ColorScales::setSubmode( guint submode ) -{ - g_return_if_fail (_csel != NULL); - g_return_if_fail (SP_IS_COLOR_SCALES (_csel)); - g_return_if_fail (submode < 3); - - switch ( submode ) - { - default: - case 0: - setMode(SP_COLOR_SCALES_MODE_RGB); - break; - case 1: - setMode(SP_COLOR_SCALES_MODE_HSV); - break; - case 2: - setMode(SP_COLOR_SCALES_MODE_CMYK); - break; - } -} - -guint ColorScales::getSubmode() const -{ - guint submode = 0; - - switch ( _mode ) - { - case SP_COLOR_SCALES_MODE_HSV: - submode = 1; - break; - case SP_COLOR_SCALES_MODE_CMYK: - submode = 2; - break; - case SP_COLOR_SCALES_MODE_RGB: - default: - submode = 0; - } - - return submode; -} - -void ColorScales::_adjustmentAnyChanged( GtkAdjustment *adjustment, SPColorScales *cs ) -{ - gint channel = GPOINTER_TO_INT (g_object_get_data(G_OBJECT (adjustment), "channel")); - - _adjustmentChanged(cs, channel); -} - -void ColorScales::_sliderAnyGrabbed( SPColorSlider *slider, SPColorScales *cs ) -{ - (void)slider; - ColorScales* scales = static_cast<ColorScales*>(SP_COLOR_SELECTOR(cs)->base); - if (!scales->_dragging) { - scales->_dragging = TRUE; - scales->_grabbed(); - scales->_recalcColor( FALSE ); - } -} - -void ColorScales::_sliderAnyReleased( SPColorSlider *slider, SPColorScales *cs ) -{ - (void)slider; - ColorScales* scales = static_cast<ColorScales*>(SP_COLOR_SELECTOR(cs)->base); - if (scales->_dragging) { - scales->_dragging = FALSE; - scales->_released(); - scales->_recalcColor( FALSE ); - } -} - -void ColorScales::_sliderAnyChanged( SPColorSlider *slider, SPColorScales *cs ) -{ - (void)slider; - ColorScales* scales = static_cast<ColorScales*>(SP_COLOR_SELECTOR(cs)->base); - - scales->_recalcColor( TRUE ); -} - -void ColorScales::_adjustmentChanged( SPColorScales *cs, guint channel ) -{ - ColorScales* scales = static_cast<ColorScales*>(SP_COLOR_SELECTOR(cs)->base); - if (scales->_updating) return; - - scales->_updating = TRUE; - - scales->_updateSliders( (1 << channel) ); - - scales->_recalcColor (TRUE); - - scales->_updating = FALSE; -} - -void ColorScales::_updateSliders( guint channels ) -{ - gfloat rgb0[3], rgbm[3], rgb1[3]; -#ifdef SPCS_PREVIEW - guint32 rgba; -#endif - switch (_mode) { - case SP_COLOR_SCALES_MODE_RGB: - if ((channels != CSC_CHANNEL_R) && (channels != CSC_CHANNEL_A)) { - /* Update red */ - sp_color_slider_set_colors (SP_COLOR_SLIDER (_s[0]), - SP_RGBA32_F_COMPOSE (0.0, getScaled(_a[1]), getScaled(_a[2]), 1.0), - SP_RGBA32_F_COMPOSE (0.5, getScaled(_a[1]), getScaled(_a[2]), 1.0), - SP_RGBA32_F_COMPOSE (1.0, getScaled(_a[1]), getScaled(_a[2]), 1.0)); - } - if ((channels != CSC_CHANNEL_G) && (channels != CSC_CHANNEL_A)) { - /* Update green */ - sp_color_slider_set_colors (SP_COLOR_SLIDER (_s[1]), - SP_RGBA32_F_COMPOSE (getScaled(_a[0]), 0.0, getScaled(_a[2]), 1.0), - SP_RGBA32_F_COMPOSE (getScaled(_a[0]), 0.5, getScaled(_a[2]), 1.0), - SP_RGBA32_F_COMPOSE (getScaled(_a[0]), 1.0, getScaled(_a[2]), 1.0)); - } - if ((channels != CSC_CHANNEL_B) && (channels != CSC_CHANNEL_A)) { - /* Update blue */ - sp_color_slider_set_colors (SP_COLOR_SLIDER (_s[2]), - SP_RGBA32_F_COMPOSE (getScaled(_a[0]), getScaled(_a[1]), 0.0, 1.0), - SP_RGBA32_F_COMPOSE (getScaled(_a[0]), getScaled(_a[1]), 0.5, 1.0), - SP_RGBA32_F_COMPOSE (getScaled(_a[0]), getScaled(_a[1]), 1.0, 1.0)); - } - if (channels != CSC_CHANNEL_A) { - /* Update alpha */ - sp_color_slider_set_colors (SP_COLOR_SLIDER (_s[3]), - SP_RGBA32_F_COMPOSE (getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), 0.0), - SP_RGBA32_F_COMPOSE (getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), 0.5), - SP_RGBA32_F_COMPOSE (getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), 1.0)); - } - break; - case SP_COLOR_SCALES_MODE_HSV: - /* Hue is never updated */ - if ((channels != CSC_CHANNEL_S) && (channels != CSC_CHANNEL_A)) { - /* Update saturation */ - sp_color_hsl_to_rgb_floatv (rgb0, getScaled(_a[0]), 0.0, getScaled(_a[2])); - sp_color_hsl_to_rgb_floatv (rgbm, getScaled(_a[0]), 0.5, getScaled(_a[2])); - sp_color_hsl_to_rgb_floatv (rgb1, getScaled(_a[0]), 1.0, getScaled(_a[2])); - sp_color_slider_set_colors (SP_COLOR_SLIDER (_s[1]), - SP_RGBA32_F_COMPOSE (rgb0[0], rgb0[1], rgb0[2], 1.0), - SP_RGBA32_F_COMPOSE (rgbm[0], rgbm[1], rgbm[2], 1.0), - SP_RGBA32_F_COMPOSE (rgb1[0], rgb1[1], rgb1[2], 1.0)); - } - if ((channels != CSC_CHANNEL_V) && (channels != CSC_CHANNEL_A)) { - /* Update value */ - sp_color_hsl_to_rgb_floatv (rgb0, getScaled(_a[0]), getScaled(_a[1]), 0.0); - sp_color_hsl_to_rgb_floatv (rgbm, getScaled(_a[0]), getScaled(_a[1]), 0.5); - sp_color_hsl_to_rgb_floatv (rgb1, getScaled(_a[0]), getScaled(_a[1]), 1.0); - sp_color_slider_set_colors (SP_COLOR_SLIDER (_s[2]), - SP_RGBA32_F_COMPOSE (rgb0[0], rgb0[1], rgb0[2], 1.0), - SP_RGBA32_F_COMPOSE (rgbm[0], rgbm[1], rgbm[2], 1.0), - SP_RGBA32_F_COMPOSE (rgb1[0], rgb1[1], rgb1[2], 1.0)); - } - if (channels != CSC_CHANNEL_A) { - /* Update alpha */ - sp_color_hsl_to_rgb_floatv (rgb0, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2])); - sp_color_slider_set_colors (SP_COLOR_SLIDER (_s[3]), - SP_RGBA32_F_COMPOSE (rgb0[0], rgb0[1], rgb0[2], 0.0), - SP_RGBA32_F_COMPOSE (rgb0[0], rgb0[1], rgb0[2], 0.5), - SP_RGBA32_F_COMPOSE (rgb0[0], rgb0[1], rgb0[2], 1.0)); - } - break; - case SP_COLOR_SCALES_MODE_CMYK: - if ((channels != CSC_CHANNEL_C) && (channels != CSC_CHANNEL_CMYKA)) { - /* Update C */ - sp_color_cmyk_to_rgb_floatv (rgb0, 0.0, getScaled(_a[1]), getScaled(_a[2]), getScaled(_a[3])); - sp_color_cmyk_to_rgb_floatv (rgbm, 0.5, getScaled(_a[1]), getScaled(_a[2]), getScaled(_a[3])); - sp_color_cmyk_to_rgb_floatv (rgb1, 1.0, getScaled(_a[1]), getScaled(_a[2]), getScaled(_a[3])); - sp_color_slider_set_colors (SP_COLOR_SLIDER (_s[0]), - SP_RGBA32_F_COMPOSE (rgb0[0], rgb0[1], rgb0[2], 1.0), - SP_RGBA32_F_COMPOSE (rgbm[0], rgbm[1], rgbm[2], 1.0), - SP_RGBA32_F_COMPOSE (rgb1[0], rgb1[1], rgb1[2], 1.0)); - } - if ((channels != CSC_CHANNEL_M) && (channels != CSC_CHANNEL_CMYKA)) { - /* Update M */ - sp_color_cmyk_to_rgb_floatv (rgb0, getScaled(_a[0]), 0.0, getScaled(_a[2]), getScaled(_a[3])); - sp_color_cmyk_to_rgb_floatv (rgbm, getScaled(_a[0]), 0.5, getScaled(_a[2]), getScaled(_a[3])); - sp_color_cmyk_to_rgb_floatv (rgb1, getScaled(_a[0]), 1.0, getScaled(_a[2]), getScaled(_a[3])); - sp_color_slider_set_colors (SP_COLOR_SLIDER (_s[1]), - SP_RGBA32_F_COMPOSE (rgb0[0], rgb0[1], rgb0[2], 1.0), - SP_RGBA32_F_COMPOSE (rgbm[0], rgbm[1], rgbm[2], 1.0), - SP_RGBA32_F_COMPOSE (rgb1[0], rgb1[1], rgb1[2], 1.0)); - } - if ((channels != CSC_CHANNEL_Y) && (channels != CSC_CHANNEL_CMYKA)) { - /* Update Y */ - sp_color_cmyk_to_rgb_floatv (rgb0, getScaled(_a[0]), getScaled(_a[1]), 0.0, getScaled(_a[3])); - sp_color_cmyk_to_rgb_floatv (rgbm, getScaled(_a[0]), getScaled(_a[1]), 0.5, getScaled(_a[3])); - sp_color_cmyk_to_rgb_floatv (rgb1, getScaled(_a[0]), getScaled(_a[1]), 1.0, getScaled(_a[3])); - sp_color_slider_set_colors (SP_COLOR_SLIDER (_s[2]), - SP_RGBA32_F_COMPOSE (rgb0[0], rgb0[1], rgb0[2], 1.0), - SP_RGBA32_F_COMPOSE (rgbm[0], rgbm[1], rgbm[2], 1.0), - SP_RGBA32_F_COMPOSE (rgb1[0], rgb1[1], rgb1[2], 1.0)); - } - if ((channels != CSC_CHANNEL_K) && (channels != CSC_CHANNEL_CMYKA)) { - /* Update K */ - sp_color_cmyk_to_rgb_floatv (rgb0, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), 0.0); - sp_color_cmyk_to_rgb_floatv (rgbm, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), 0.5); - sp_color_cmyk_to_rgb_floatv (rgb1, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), 1.0); - sp_color_slider_set_colors (SP_COLOR_SLIDER (_s[3]), - SP_RGBA32_F_COMPOSE (rgb0[0], rgb0[1], rgb0[2], 1.0), - SP_RGBA32_F_COMPOSE (rgbm[0], rgbm[1], rgbm[2], 1.0), - SP_RGBA32_F_COMPOSE (rgb1[0], rgb1[1], rgb1[2], 1.0)); - } - if (channels != CSC_CHANNEL_CMYKA) { - /* Update alpha */ - sp_color_cmyk_to_rgb_floatv (rgb0, getScaled(_a[0]), getScaled(_a[1]), getScaled(_a[2]), getScaled(_a[3])); - sp_color_slider_set_colors (SP_COLOR_SLIDER (_s[4]), - SP_RGBA32_F_COMPOSE (rgb0[0], rgb0[1], rgb0[2], 0.0), - SP_RGBA32_F_COMPOSE (rgb0[0], rgb0[1], rgb0[2], 0.5), - SP_RGBA32_F_COMPOSE (rgb0[0], rgb0[1], rgb0[2], 1.0)); - } - break; - default: - g_warning ("file %s: line %d: Illegal color selector mode", __FILE__, __LINE__); - break; - } - - // Force the internal color to be updated - if ( !_updating ) - { - _recalcColor( TRUE ); - } - -#ifdef SPCS_PREVIEW - rgba = sp_color_scales_get_rgba32 (cs); - sp_color_preview_set_rgba32 (SP_COLOR_PREVIEW (_p), rgba); -#endif -} - -static const gchar * -sp_color_scales_hue_map (void) -{ - static gchar *map = NULL; - - if (!map) { - gchar *p; - gint h; - map = g_new (gchar, 4 * 1024); - p = map; - for (h = 0; h < 1024; h++) { - gfloat rgb[3]; - sp_color_hsl_to_rgb_floatv (rgb, h / 1024.0, 1.0, 0.5); - *p++ = SP_COLOR_F_TO_U (rgb[0]); - *p++ = SP_COLOR_F_TO_U (rgb[1]); - *p++ = SP_COLOR_F_TO_U (rgb[2]); - *p++ = 255; - } - } - - return map; -} - - diff --git a/src/widgets/sp-color-scales.h b/src/widgets/sp-color-scales.h deleted file mode 100644 index 72cbafa2f..000000000 --- a/src/widgets/sp-color-scales.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef SEEN_SP_COLOR_SCALES_H -#define SEEN_SP_COLOR_SCALES_H - -#include <glib.h> - -#include <widgets/sp-color-selector.h> - -struct SPColorScales; -struct SPColorScalesClass; -struct SPColorSlider; - -typedef enum { - SP_COLOR_SCALES_MODE_NONE = 0, - SP_COLOR_SCALES_MODE_RGB = 1, - SP_COLOR_SCALES_MODE_HSV = 2, - SP_COLOR_SCALES_MODE_CMYK = 3 -} SPColorScalesMode; - - - -class ColorScales: public ColorSelector -{ -public: - static gfloat getScaled( const GtkAdjustment *a ); - static void setScaled( GtkAdjustment *a, gfloat v); - - ColorScales(SPColorSelector *csel); - virtual ~ColorScales(); - - virtual void init(); - - virtual void setSubmode(guint submode); - virtual guint getSubmode() const; - - void setMode(SPColorScalesMode mode); - SPColorScalesMode getMode() const; - - -protected: - virtual void _colorChanged(); - - static void _adjustmentAnyChanged(GtkAdjustment *adjustment, SPColorScales *cs); - static void _sliderAnyGrabbed(SPColorSlider *slider, SPColorScales *cs); - static void _sliderAnyReleased(SPColorSlider *slider, SPColorScales *cs); - static void _sliderAnyChanged(SPColorSlider *slider, SPColorScales *cs); - static void _adjustmentChanged(SPColorScales *cs, guint channel); - - void _getRgbaFloatv(gfloat *rgba); - void _getCmykaFloatv(gfloat *cmyka); - guint32 _getRgba32(); - void _updateSliders(guint channels); - void _recalcColor(gboolean changing); - - void _setRangeLimit( gdouble upper ); - - SPColorScalesMode _mode; - gdouble _rangeLimit; - gboolean _updating : 1; - gboolean _dragging : 1; - GtkAdjustment *_a[5]; /* Channel adjustments */ - GtkWidget *_s[5]; /* Channel sliders */ - GtkWidget *_b[5]; /* Spinbuttons */ - GtkWidget *_l[5]; /* Labels */ - -private: - // By default, disallow copy constructor and assignment operator - ColorScales(ColorScales const &obj); - ColorScales &operator=(ColorScales const &obj ); -}; - - - -#define SP_TYPE_COLOR_SCALES (sp_color_scales_get_type()) -#define SP_COLOR_SCALES(o) (G_TYPE_CHECK_INSTANCE_CAST((o), SP_TYPE_COLOR_SCALES, SPColorScales)) -#define SP_COLOR_SCALES_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), SP_TYPE_COLOR_SCALES, SPColorScalesClass)) -#define SP_IS_COLOR_SCALES(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), SP_TYPE_COLOR_SCALES)) -#define SP_IS_COLOR_SCALES_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), SP_TYPE_COLOR_SCALES)) - -struct SPColorScales { - SPColorSelector parent; -}; - -struct SPColorScalesClass { - SPColorSelectorClass parent_class; -}; - -GType sp_color_scales_get_type(); - -GtkWidget *sp_color_scales_new(); - -#endif /* !SEEN_SP_COLOR_SCALES_H */ - -/* - 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 : diff --git a/src/widgets/sp-color-selector.cpp b/src/widgets/sp-color-selector.cpp index e97c36431..dad0a18b0 100644 --- a/src/widgets/sp-color-selector.cpp +++ b/src/widgets/sp-color-selector.cpp @@ -6,6 +6,11 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif + +#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H +#include <glibmm/threads.h> +#endif + #include <math.h> #include <gtk/gtk.h> #include <glibmm/i18n.h> @@ -289,7 +294,7 @@ void ColorSelector::_updateInternals( const SPColor& color, gfloat alpha, gboole (_held ? "CHANGED" : "DRAGGED" ), color.toRGBA32( alpha ), (color.icc?color.icc->colorProfile.c_str():"<null>"), FOO_NAME(_csel)); #endif - g_signal_emit(G_OBJECT(_csel), csel_signals[_held ? CHANGED : DRAGGED], 0); + g_signal_emit(G_OBJECT(_csel), csel_signals[_held ? DRAGGED : CHANGED], 0); } } diff --git a/src/widgets/sp-color-selector.h b/src/widgets/sp-color-selector.h index 30061774a..308a5519c 100644 --- a/src/widgets/sp-color-selector.h +++ b/src/widgets/sp-color-selector.h @@ -1,6 +1,14 @@ #ifndef SEEN_SP_COLOR_SELECTOR_H #define SEEN_SP_COLOR_SELECTOR_H +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H +#include <glibmm/threads.h> +#endif + #include <gtk/gtk.h> #include "color.h" diff --git a/src/widgets/sp-color-slider.cpp b/src/widgets/sp-color-slider.cpp deleted file mode 100644 index ab7e2cd84..000000000 --- a/src/widgets/sp-color-slider.cpp +++ /dev/null @@ -1,749 +0,0 @@ -/* - * A slider with colored background - * - * Author: - * Lauris Kaplinski <lauris@kaplinski.com> - * bulia byak <buliabyak@users.sf.net> - * - * Copyright (C) 2001-2002 Lauris Kaplinski - * - * This code is in public domain - */ - -#include <gtk/gtk.h> -#include "sp-color-scales.h" -#include "sp-color-slider.h" -#include "preferences.h" - -#define SLIDER_WIDTH 96 -#define SLIDER_HEIGHT 8 -#define ARROW_SIZE 7 - -enum { - GRABBED, - DRAGGED, - RELEASED, - CHANGED, - LAST_SIGNAL -}; - -static void sp_color_slider_dispose(GObject *object); - -static void sp_color_slider_realize (GtkWidget *widget); -static void sp_color_slider_size_request (GtkWidget *widget, GtkRequisition *requisition); - -#if GTK_CHECK_VERSION(3,0,0) -static void sp_color_slider_get_preferred_width(GtkWidget *widget, - gint *minimal_width, - gint *natural_width); - -static void sp_color_slider_get_preferred_height(GtkWidget *widget, - gint *minimal_height, - gint *natural_height); -#else -static gboolean sp_color_slider_expose(GtkWidget *widget, GdkEventExpose *event); -#endif - -static void sp_color_slider_size_allocate (GtkWidget *widget, GtkAllocation *allocation); - -static gboolean sp_color_slider_draw(GtkWidget *widget, cairo_t *cr); - -static gint sp_color_slider_button_press (GtkWidget *widget, GdkEventButton *event); -static gint sp_color_slider_button_release (GtkWidget *widget, GdkEventButton *event); -static gint sp_color_slider_motion_notify (GtkWidget *widget, GdkEventMotion *event); - -static void sp_color_slider_adjustment_changed (GtkAdjustment *adjustment, SPColorSlider *slider); -static void sp_color_slider_adjustment_value_changed (GtkAdjustment *adjustment, SPColorSlider *slider); - -static const guchar *sp_color_slider_render_gradient (gint x0, gint y0, gint width, gint height, - gint c[], gint dc[], guint b0, guint b1, guint mask); -static const guchar *sp_color_slider_render_map (gint x0, gint y0, gint width, gint height, - guchar *map, gint start, gint step, guint b0, guint b1, guint mask); - -static guint slider_signals[LAST_SIGNAL] = {0}; - -G_DEFINE_TYPE(SPColorSlider, sp_color_slider, GTK_TYPE_WIDGET); - -static void sp_color_slider_class_init(SPColorSliderClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS(klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); - - slider_signals[GRABBED] = g_signal_new ("grabbed", - G_TYPE_FROM_CLASS(object_class), - (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE), - G_STRUCT_OFFSET (SPColorSliderClass, grabbed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - slider_signals[DRAGGED] = g_signal_new ("dragged", - G_TYPE_FROM_CLASS(object_class), - (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE), - G_STRUCT_OFFSET (SPColorSliderClass, dragged), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - slider_signals[RELEASED] = g_signal_new ("released", - G_TYPE_FROM_CLASS(object_class), - (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE), - G_STRUCT_OFFSET (SPColorSliderClass, released), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - slider_signals[CHANGED] = g_signal_new ("changed", - G_TYPE_FROM_CLASS(object_class), - (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE), - G_STRUCT_OFFSET (SPColorSliderClass, changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - object_class->dispose = sp_color_slider_dispose; - - widget_class->realize = sp_color_slider_realize; -#if GTK_CHECK_VERSION(3,0,0) - widget_class->get_preferred_width = sp_color_slider_get_preferred_width; - widget_class->get_preferred_height = sp_color_slider_get_preferred_height; - widget_class->draw = sp_color_slider_draw; -#else - widget_class->size_request = sp_color_slider_size_request; - widget_class->expose_event = sp_color_slider_expose; -#endif - widget_class->size_allocate = sp_color_slider_size_allocate; -/* widget_class->draw_focus = sp_color_slider_draw_focus; */ -/* widget_class->draw_default = sp_color_slider_draw_default; */ - - widget_class->button_press_event = sp_color_slider_button_press; - widget_class->button_release_event = sp_color_slider_button_release; - widget_class->motion_notify_event = sp_color_slider_motion_notify; -} - -static void -sp_color_slider_init (SPColorSlider *slider) -{ - /* We are widget with window */ - gtk_widget_set_has_window (GTK_WIDGET(slider), TRUE); - - slider->dragging = FALSE; - - slider->adjustment = NULL; - slider->value = 0.0; - - slider->c0[0] = 0x00; - slider->c0[1] = 0x00; - slider->c0[2] = 0x00; - slider->c0[3] = 0xff; - - slider->cm[0] = 0xff; - slider->cm[1] = 0x00; - slider->cm[2] = 0x00; - slider->cm[3] = 0xff; - - slider->c1[0] = 0xff; - slider->c1[1] = 0xff; - slider->c1[2] = 0xff; - slider->c1[3] = 0xff; - - slider->b0 = 0x5f; - slider->b1 = 0xa0; - slider->bmask = 0x08; - - slider->map = NULL; -} - -static void sp_color_slider_dispose(GObject *object) -{ - SPColorSlider *slider = SP_COLOR_SLIDER (object); - - if (slider->adjustment) { - g_signal_handlers_disconnect_matched (G_OBJECT (slider->adjustment), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, slider); - g_object_unref (slider->adjustment); - slider->adjustment = NULL; - } - - if (G_OBJECT_CLASS(sp_color_slider_parent_class)->dispose) - G_OBJECT_CLASS(sp_color_slider_parent_class)->dispose (object); -} - -static void -sp_color_slider_realize (GtkWidget *widget) -{ - GdkWindowAttr attributes; - gint attributes_mask; - GtkAllocation allocation; - - gtk_widget_get_allocation(widget, &allocation); - gtk_widget_set_realized (widget, TRUE); - - attributes.window_type = GDK_WINDOW_CHILD; - attributes.x = allocation.x; - attributes.y = allocation.y; - attributes.width = allocation.width; - attributes.height = allocation.height; - attributes.wclass = GDK_INPUT_OUTPUT; - attributes.visual = gdk_screen_get_system_visual(gdk_screen_get_default()); - -#if !GTK_CHECK_VERSION(3,0,0) - attributes.colormap = gdk_screen_get_system_colormap(gdk_screen_get_default()); -#endif - - attributes.event_mask = gtk_widget_get_events (widget); - attributes.event_mask |= (GDK_EXPOSURE_MASK | - GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK | - GDK_ENTER_NOTIFY_MASK | - GDK_LEAVE_NOTIFY_MASK); -#if GTK_CHECK_VERSION(3,0,0) - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL; -#else - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; -#endif - - gtk_widget_set_window(widget, - gdk_window_new(gtk_widget_get_parent_window(widget), - &attributes, attributes_mask)); - - gdk_window_set_user_data(gtk_widget_get_window(widget), widget); - -#if !GTK_CHECK_VERSION(3,0,0) - // This doesn't do anything in GTK+ 3 - gtk_widget_set_style(widget, - gtk_style_attach(gtk_widget_get_style(widget), - gtk_widget_get_window(widget))); -#endif -} - -static void -sp_color_slider_size_request (GtkWidget *widget, GtkRequisition *requisition) -{ - GtkStyle *style = gtk_widget_get_style(widget); - requisition->width = SLIDER_WIDTH + style->xthickness * 2; - requisition->height = SLIDER_HEIGHT + style->ythickness * 2; -} - -#if GTK_CHECK_VERSION(3,0,0) -static void sp_color_slider_get_preferred_width(GtkWidget *widget, gint *minimal_width, gint *natural_width) -{ - GtkRequisition requisition; - sp_color_slider_size_request(widget, &requisition); - *minimal_width = *natural_width = requisition.width; -} - -static void sp_color_slider_get_preferred_height(GtkWidget *widget, gint *minimal_height, gint *natural_height) -{ - GtkRequisition requisition; - sp_color_slider_size_request(widget, &requisition); - *minimal_height = *natural_height = requisition.height; -} -#endif - -static void -sp_color_slider_size_allocate (GtkWidget *widget, GtkAllocation *allocation) -{ - gtk_widget_set_allocation(widget, allocation); - - if (gtk_widget_get_realized (widget)) { - /* Resize GdkWindow */ - gdk_window_move_resize(gtk_widget_get_window(widget), - allocation->x, allocation->y, - allocation->width, allocation->height); - } -} - -#if !GTK_CHECK_VERSION(3,0,0) -static gboolean sp_color_slider_expose(GtkWidget *widget, GdkEventExpose * /*event*/) -{ - gboolean result = FALSE; - - if (gtk_widget_is_drawable(widget)) { - GdkWindow *window = gtk_widget_get_window(widget); - cairo_t *cr = gdk_cairo_create(window); - result = sp_color_slider_draw(widget, cr); - cairo_destroy(cr); - } - - return result; -} -#endif - -static gint -sp_color_slider_button_press (GtkWidget *widget, GdkEventButton *event) -{ - SPColorSlider *slider; - - slider = SP_COLOR_SLIDER (widget); - - if (event->button == 1) { - GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); - gint cx, cw; - cx = gtk_widget_get_style(widget)->xthickness; - cw = allocation.width - 2 * cx; - g_signal_emit (G_OBJECT (slider), slider_signals[GRABBED], 0); - slider->dragging = TRUE; - slider->oldvalue = slider->value; - ColorScales::setScaled( slider->adjustment, CLAMP ((gfloat) (event->x - cx) / cw, 0.0, 1.0) ); - g_signal_emit (G_OBJECT (slider), slider_signals[DRAGGED], 0); - -#if GTK_CHECK_VERSION(3,0,0) - gdk_device_grab(gdk_event_get_device(reinterpret_cast<GdkEvent *>(event)), - gtk_widget_get_window(widget), - GDK_OWNERSHIP_NONE, - FALSE, - static_cast<GdkEventMask>(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK), - NULL, - event->time); -#else - gdk_pointer_grab(gtk_widget_get_window(widget), FALSE, - static_cast<GdkEventMask>(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK), - NULL, NULL, event->time); -#endif - } - - return FALSE; -} - -static gint -sp_color_slider_button_release (GtkWidget *widget, GdkEventButton *event) -{ - SPColorSlider *slider; - - slider = SP_COLOR_SLIDER (widget); - - if (event->button == 1) { - -#if GTK_CHECK_VERSION(3,0,0) - gdk_device_ungrab(gdk_event_get_device(reinterpret_cast<GdkEvent *>(event)), - gdk_event_get_time(reinterpret_cast<GdkEvent *>(event))); -#else - gdk_pointer_ungrab (event->time); -#endif - - slider->dragging = FALSE; - g_signal_emit (G_OBJECT (slider), slider_signals[RELEASED], 0); - if (slider->value != slider->oldvalue) g_signal_emit (G_OBJECT (slider), slider_signals[CHANGED], 0); - } - - return FALSE; -} - -static gint -sp_color_slider_motion_notify (GtkWidget *widget, GdkEventMotion *event) -{ - SPColorSlider *slider; - - slider = SP_COLOR_SLIDER (widget); - - if (slider->dragging) { - gint cx, cw; - GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); - cx = gtk_widget_get_style(widget)->xthickness; - cw = allocation.width - 2 * cx; - ColorScales::setScaled( slider->adjustment, CLAMP ((gfloat) (event->x - cx) / cw, 0.0, 1.0) ); - g_signal_emit (G_OBJECT (slider), slider_signals[DRAGGED], 0); - } - - return FALSE; -} - -GtkWidget *sp_color_slider_new(GtkAdjustment *adjustment) -{ - SPColorSlider *slider = SP_COLOR_SLIDER(g_object_new(SP_TYPE_COLOR_SLIDER, NULL)); - - sp_color_slider_set_adjustment (slider, adjustment); - - return GTK_WIDGET (slider); -} - -void sp_color_slider_set_adjustment(SPColorSlider *slider, GtkAdjustment *adjustment) -{ - g_return_if_fail (slider != NULL); - g_return_if_fail (SP_IS_COLOR_SLIDER (slider)); - - if (!adjustment) { - adjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 1.0, 0.01, 0.0, 0.0)); - } else { - gtk_adjustment_set_page_increment(adjustment, 0.0); - gtk_adjustment_set_page_size(adjustment, 0.0); - } - - if (slider->adjustment != adjustment) { - if (slider->adjustment) { - g_signal_handlers_disconnect_matched (G_OBJECT (slider->adjustment), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, slider); - g_object_unref (slider->adjustment); - } - - slider->adjustment = adjustment; - g_object_ref (adjustment); - g_object_ref_sink (adjustment); - - g_signal_connect (G_OBJECT (adjustment), "changed", - G_CALLBACK (sp_color_slider_adjustment_changed), slider); - g_signal_connect (G_OBJECT (adjustment), "value_changed", - G_CALLBACK (sp_color_slider_adjustment_value_changed), slider); - - slider->value = ColorScales::getScaled( adjustment ); - - sp_color_slider_adjustment_changed (adjustment, slider); - } -} - -void -sp_color_slider_set_colors (SPColorSlider *slider, guint32 start, guint32 mid, guint32 end) -{ - g_return_if_fail (slider != NULL); - g_return_if_fail (SP_IS_COLOR_SLIDER (slider)); - - // Remove any map, if set - slider->map = 0; - - slider->c0[0] = start >> 24; - slider->c0[1] = (start >> 16) & 0xff; - slider->c0[2] = (start >> 8) & 0xff; - slider->c0[3] = start & 0xff; - - slider->cm[0] = mid >> 24; - slider->cm[1] = (mid >> 16) & 0xff; - slider->cm[2] = (mid >> 8) & 0xff; - slider->cm[3] = mid & 0xff; - - slider->c1[0] = end >> 24; - slider->c1[1] = (end >> 16) & 0xff; - slider->c1[2] = (end >> 8) & 0xff; - slider->c1[3] = end & 0xff; - - gtk_widget_queue_draw (GTK_WIDGET (slider)); -} - -void -sp_color_slider_set_map (SPColorSlider *slider, const guchar *map) -{ - g_return_if_fail (slider != NULL); - g_return_if_fail (SP_IS_COLOR_SLIDER (slider)); - - slider->map = const_cast<guchar *>(map); - - gtk_widget_queue_draw (GTK_WIDGET (slider)); -} - -void -sp_color_slider_set_background (SPColorSlider *slider, guint dark, guint light, guint size) -{ - g_return_if_fail (slider != NULL); - g_return_if_fail (SP_IS_COLOR_SLIDER (slider)); - - slider->b0 = dark; - slider->b1 = light; - slider->bmask = size; - - gtk_widget_queue_draw (GTK_WIDGET (slider)); -} - -static void -sp_color_slider_adjustment_changed (GtkAdjustment */*adjustment*/, SPColorSlider *slider) -{ - gtk_widget_queue_draw (GTK_WIDGET (slider)); -} - -static void -sp_color_slider_adjustment_value_changed (GtkAdjustment *adjustment, SPColorSlider *slider) -{ - GtkWidget *widget; - - widget = GTK_WIDGET (slider); - - if (slider->value != ColorScales::getScaled( adjustment )) { - gint cx, cy, cw, ch; - GtkStyle *style = gtk_widget_get_style(widget); - GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); - cx = style->xthickness; - cy = style->ythickness; - cw = allocation.width - 2 * cx; - ch = allocation.height - 2 * cy; - if ((gint) (ColorScales::getScaled( adjustment ) * cw) != (gint) (slider->value * cw)) { - gint ax, ay; - gfloat value; - value = slider->value; - slider->value = ColorScales::getScaled( adjustment ); - ax = (int)(cx + value * cw - ARROW_SIZE / 2 - 2); - ay = cy; - gtk_widget_queue_draw_area (widget, ax, ay, ARROW_SIZE + 4, ch); - ax = (int)(cx + slider->value * cw - ARROW_SIZE / 2 - 2); - ay = cy; - gtk_widget_queue_draw_area (widget, ax, ay, ARROW_SIZE + 4, ch); - } else { - slider->value = ColorScales::getScaled( adjustment ); - } - } -} - -static gboolean sp_color_slider_draw(GtkWidget *widget, cairo_t *cr) -{ - SPColorSlider *slider = SP_COLOR_SLIDER(widget); - - gboolean colorsOnTop = Inkscape::Preferences::get()->getBool("/options/workarounds/colorsontop", false); - - GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); - -#if GTK_CHECK_VERSION(3,0,0) - GtkStyleContext *context = gtk_widget_get_style_context(widget); -#else - GdkWindow *window = gtk_widget_get_window(widget); - GtkStyle *style = gtk_widget_get_style(widget); -#endif - - // Draw shadow - if (colorsOnTop) { -#if GTK_CHECK_VERSION(3,0,0) - gtk_render_frame(context, - cr, - 0, 0, - allocation.width, allocation.height); -#else - gtk_paint_shadow( style, window, - gtk_widget_get_state(widget), GTK_SHADOW_IN, - NULL, widget, "colorslider", - 0, 0, - allocation.width, allocation.height); -#endif - } - - /* Paintable part of color gradient area */ - GdkRectangle carea; - -#if GTK_CHECK_VERSION(3,0,0) - GtkBorder padding; - - gtk_style_context_get_padding(context, - gtk_widget_get_state_flags(widget), - &padding); - - carea.x = padding.left; - carea.y = padding.top; -#else - carea.x = style->xthickness; - carea.y = style->ythickness; -#endif - - carea.width = allocation.width - 2 * carea.x; - carea.height = allocation.height - 2 * carea.y; - - if (slider->map) { - /* Render map pixelstore */ - gint d = (1024 << 16) / carea.width; - gint s = 0; - - const guchar *b = sp_color_slider_render_map(0, 0, carea.width, carea.height, - slider->map, s, d, - slider->b0, slider->b1, slider->bmask); - - if (b != NULL && carea.width > 0) { - GdkPixbuf *pb = gdk_pixbuf_new_from_data (b, GDK_COLORSPACE_RGB, - 0, 8, carea.width, carea.height, carea.width * 3, NULL, NULL); - - gdk_cairo_set_source_pixbuf(cr, pb, carea.x, carea.y); - cairo_paint(cr); - g_object_unref(pb); - } - - } else { - gint c[4], dc[4]; - - /* Render gradient */ - - // part 1: from c0 to cm - if (carea.width > 0) { - for (gint i = 0; i < 4; i++) { - c[i] = slider->c0[i] << 16; - dc[i] = ((slider->cm[i] << 16) - c[i]) / (carea.width/2); - } - guint wi = carea.width/2; - const guchar *b = sp_color_slider_render_gradient(0, 0, wi, carea.height, - c, dc, slider->b0, slider->b1, slider->bmask); - - /* Draw pixelstore 1 */ - if (b != NULL && wi > 0) { - GdkPixbuf *pb = gdk_pixbuf_new_from_data (b, GDK_COLORSPACE_RGB, - 0, 8, wi, carea.height, wi * 3, NULL, NULL); - - gdk_cairo_set_source_pixbuf(cr, pb, carea.x, carea.y); - cairo_paint(cr); - g_object_unref(pb); - } - } - - // part 2: from cm to c1 - if (carea.width > 0) { - for (gint i = 0; i < 4; i++) { - c[i] = slider->cm[i] << 16; - dc[i] = ((slider->c1[i] << 16) - c[i]) / (carea.width/2); - } - guint wi = carea.width/2; - const guchar *b = sp_color_slider_render_gradient(carea.width/2, 0, wi, carea.height, - c, dc, - slider->b0, slider->b1, slider->bmask); - - /* Draw pixelstore 2 */ - if (b != NULL && wi > 0) { - GdkPixbuf *pb = gdk_pixbuf_new_from_data (b, GDK_COLORSPACE_RGB, - 0, 8, wi, carea.height, wi * 3, NULL, NULL); - - gdk_cairo_set_source_pixbuf(cr, pb, carea.width/2 + carea.x, carea.y); - cairo_paint(cr); - - g_object_unref(pb); - } - } - } - - /* Draw shadow */ - if (!colorsOnTop) { -#if GTK_CHECK_VERSION(3,0,0) - gtk_render_frame(context, - cr, - 0, 0, - allocation.width, allocation.height); -#else - gtk_paint_shadow( style, window, - gtk_widget_get_state(widget), GTK_SHADOW_IN, - NULL, widget, "colorslider", - 0, 0, - allocation.width, allocation.height); -#endif - } - - /* Draw arrow */ - gint x = (int)(slider->value * (carea.width - 1) - ARROW_SIZE / 2 + carea.x); - gint y1 = carea.y; - gint y2 = carea.y + carea.height - 1; - cairo_set_line_width(cr, 1.0); - - // Define top arrow - cairo_move_to(cr, x - 0.5, y1 + 0.5); - cairo_line_to(cr, x + ARROW_SIZE - 0.5, y1 + 0.5); - cairo_line_to(cr, x + (ARROW_SIZE-1)/2.0, y1 + ARROW_SIZE/2.0 + 0.5); - cairo_line_to(cr, x - 0.5, y1 + 0.5); - - // Define bottom arrow - cairo_move_to(cr, x - 0.5, y2 + 0.5); - cairo_line_to(cr, x + ARROW_SIZE - 0.5, y2 + 0.5); - cairo_line_to(cr, x + (ARROW_SIZE-1)/2.0, y2 - ARROW_SIZE/2.0 + 0.5); - cairo_line_to(cr, x - 0.5, y2 + 0.5); - - // Render both arrows - cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); - cairo_stroke_preserve(cr); - cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); - cairo_fill(cr); - - return FALSE; -} - -/* Colors are << 16 */ - -static const guchar * -sp_color_slider_render_gradient (gint x0, gint y0, gint width, gint height, - gint c[], gint dc[], guint b0, guint b1, guint mask) -{ - static guchar *buf = NULL; - static gint bs = 0; - guchar *dp; - gint x, y; - guint r, g, b, a; - - if (buf && (bs < width * height)) { - g_free (buf); - buf = NULL; - } - if (!buf) { - buf = g_new (guchar, width * height * 3); - bs = width * height; - } - - dp = buf; - r = c[0]; - g = c[1]; - b = c[2]; - a = c[3]; - for (x = x0; x < x0 + width; x++) { - gint cr, cg, cb, ca; - guchar *d; - cr = r >> 16; - cg = g >> 16; - cb = b >> 16; - ca = a >> 16; - d = dp; - for (y = y0; y < y0 + height; y++) { - guint bg, fc; - /* Background value */ - bg = ((x & mask) ^ (y & mask)) ? b0 : b1; - fc = (cr - bg) * ca; - d[0] = bg + ((fc + (fc >> 8) + 0x80) >> 8); - fc = (cg - bg) * ca; - d[1] = bg + ((fc + (fc >> 8) + 0x80) >> 8); - fc = (cb - bg) * ca; - d[2] = bg + ((fc + (fc >> 8) + 0x80) >> 8); - d += 3 * width; - } - r += dc[0]; - g += dc[1]; - b += dc[2]; - a += dc[3]; - dp += 3; - } - - return buf; -} - -/* Positions are << 16 */ - -static const guchar * -sp_color_slider_render_map (gint x0, gint y0, gint width, gint height, - guchar *map, gint start, gint step, guint b0, guint b1, guint mask) -{ - static guchar *buf = NULL; - static gint bs = 0; - guchar *dp; - gint x, y; - - if (buf && (bs < width * height)) { - g_free (buf); - buf = NULL; - } - if (!buf) { - buf = g_new (guchar, width * height * 3); - bs = width * height; - } - - dp = buf; - for (x = x0; x < x0 + width; x++) { - gint cr, cg, cb, ca; - guchar *d = dp; - guchar *sp = map + 4 * (start >> 16); - cr = *sp++; - cg = *sp++; - cb = *sp++; - ca = *sp++; - for (y = y0; y < y0 + height; y++) { - guint bg, fc; - /* Background value */ - bg = ((x & mask) ^ (y & mask)) ? b0 : b1; - fc = (cr - bg) * ca; - d[0] = bg + ((fc + (fc >> 8) + 0x80) >> 8); - fc = (cg - bg) * ca; - d[1] = bg + ((fc + (fc >> 8) + 0x80) >> 8); - fc = (cb - bg) * ca; - d[2] = bg + ((fc + (fc >> 8) + 0x80) >> 8); - d += 3 * width; - } - dp += 3; - start += step; - } - - return buf; -} - diff --git a/src/widgets/sp-color-slider.h b/src/widgets/sp-color-slider.h deleted file mode 100644 index b81d62e41..000000000 --- a/src/widgets/sp-color-slider.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef __SP_COLOR_SLIDER_H__ -#define __SP_COLOR_SLIDER_H__ - -/* - * A slider with colored background - * - * Author: - * Lauris Kaplinski <lauris@kaplinski.com> - * - * Copyright (C) 2001-2002 Lauris Kaplinski - * - * This code is in public domain - */ - -#include <gtk/gtk.h> - -#define SP_TYPE_COLOR_SLIDER (sp_color_slider_get_type ()) -#define SP_COLOR_SLIDER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SP_TYPE_COLOR_SLIDER, SPColorSlider)) -#define SP_COLOR_SLIDER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), SP_TYPE_COLOR_SLIDER, SPColorSliderClass)) -#define SP_IS_COLOR_SLIDER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SP_TYPE_COLOR_SLIDER)) -#define SP_IS_COLOR_SLIDER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SP_TYPE_COLOR_SLIDER)) - -struct SPColorSlider { - GtkWidget widget; - - guint dragging : 1; - - GtkAdjustment *adjustment; - - gfloat value; - gfloat oldvalue; - guchar c0[4], cm[4], c1[4]; - guchar b0, b1; - guchar bmask; - - gint mapsize; - guchar *map; -}; - -struct SPColorSliderClass { - GtkWidgetClass parent_class; - - void (* grabbed) (SPColorSlider *slider); - void (* dragged) (SPColorSlider *slider); - void (* released) (SPColorSlider *slider); - void (* changed) (SPColorSlider *slider); -}; - -GType sp_color_slider_get_type (void); - -GtkWidget *sp_color_slider_new (GtkAdjustment *adjustment); - -void sp_color_slider_set_adjustment (SPColorSlider *slider, GtkAdjustment *adjustment); -void sp_color_slider_set_colors (SPColorSlider *slider, guint32 start, guint32 mid, guint32 end); -void sp_color_slider_set_map (SPColorSlider *slider, const guchar *map); -void sp_color_slider_set_background (SPColorSlider *slider, guint dark, guint light, guint size); - - - -#endif diff --git a/src/widgets/sp-color-wheel-selector.cpp b/src/widgets/sp-color-wheel-selector.cpp deleted file mode 100644 index 6cfa7c14d..000000000 --- a/src/widgets/sp-color-wheel-selector.cpp +++ /dev/null @@ -1,348 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include <math.h> -#include <gtk/gtk.h> -#include <glibmm/i18n.h> -#include "ui/dialog-events.h" -#include "sp-color-wheel-selector.h" -#include "sp-color-scales.h" -#include "sp-color-slider.h" -#include "sp-color-icc-selector.h" -#include "../svg/svg-icc-color.h" -#include "ui/widget/gimpcolorwheel.h" - -G_BEGIN_DECLS - -static void sp_color_wheel_selector_dispose(GObject *object); - -static void sp_color_wheel_selector_show_all (GtkWidget *widget); -static void sp_color_wheel_selector_hide(GtkWidget *widget); - - -G_END_DECLS - -#define XPAD 4 -#define YPAD 1 - -G_DEFINE_TYPE(SPColorWheelSelector, sp_color_wheel_selector, SP_TYPE_COLOR_SELECTOR); - -static void sp_color_wheel_selector_class_init(SPColorWheelSelectorClass *klass) -{ - static const gchar* nameset[] = {N_("Wheel"), 0}; - GObjectClass *object_class = G_OBJECT_CLASS(klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); - SPColorSelectorClass *selector_class = SP_COLOR_SELECTOR_CLASS (klass); - - selector_class->name = nameset; - selector_class->submode_count = 1; - - object_class->dispose = sp_color_wheel_selector_dispose; - - widget_class->show_all = sp_color_wheel_selector_show_all; - widget_class->hide = sp_color_wheel_selector_hide; -} - -ColorWheelSelector::ColorWheelSelector( SPColorSelector* csel ) - : ColorSelector( csel ), - _updating( FALSE ), - _dragging( FALSE ), - _adj(0), - _wheel(0), - _slider(0), - _sbtn(0), - _label(0) -{ -} - -ColorWheelSelector::~ColorWheelSelector() -{ - _adj = 0; - _wheel = 0; - _sbtn = 0; - _label = 0; -} - -void sp_color_wheel_selector_init (SPColorWheelSelector *cs) -{ - SP_COLOR_SELECTOR(cs)->base = new ColorWheelSelector( SP_COLOR_SELECTOR(cs) ); - - if ( SP_COLOR_SELECTOR(cs)->base ) - { - SP_COLOR_SELECTOR(cs)->base->init(); - } -} - -void ColorWheelSelector::init() -{ - gint row = 0; - - _updating = FALSE; - _dragging = FALSE; - -#if GTK_CHECK_VERSION(3,0,0) - GtkWidget *t = gtk_grid_new(); -#else - GtkWidget *t = gtk_table_new (5, 3, FALSE); -#endif - - gtk_widget_show (t); - gtk_box_pack_start (GTK_BOX (_csel), t, TRUE, TRUE, 0); - - /* Create components */ - row = 0; - - _wheel = gimp_color_wheel_new(); - gtk_widget_show( _wheel ); - -#if GTK_CHECK_VERSION(3,0,0) - gtk_widget_set_halign(_wheel, GTK_ALIGN_FILL); - gtk_widget_set_valign(_wheel, GTK_ALIGN_FILL); - gtk_widget_set_hexpand(_wheel, TRUE); - gtk_widget_set_vexpand(_wheel, TRUE); - gtk_grid_attach(GTK_GRID(t), _wheel, 0, row, 3, 1); -#else - gtk_table_attach(GTK_TABLE(t), _wheel, 0, 3, row, row + 1, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), 0, 0); -#endif - - row++; - - /* Label */ - _label = gtk_label_new_with_mnemonic (_("_A:")); - gtk_misc_set_alignment (GTK_MISC (_label), 1.0, 0.5); - gtk_widget_show (_label); - -#if GTK_CHECK_VERSION(3,0,0) - #if GTK_CHECK_VERSION(3,12,0) - gtk_widget_set_margin_start(_label, XPAD); - gtk_widget_set_margin_end(_label, XPAD); - #else - gtk_widget_set_margin_left(_label, XPAD); - gtk_widget_set_margin_right(_label, XPAD); - #endif - gtk_widget_set_margin_top(_label, YPAD); - gtk_widget_set_margin_bottom(_label, YPAD); - gtk_widget_set_halign(_label, GTK_ALIGN_FILL); - gtk_widget_set_valign(_label, GTK_ALIGN_FILL); - gtk_grid_attach(GTK_GRID(t), _label, 0, row, 1, 1); -#else - gtk_table_attach (GTK_TABLE (t), _label, 0, 1, row, row + 1, GTK_FILL, GTK_FILL, XPAD, YPAD); -#endif - - /* Adjustment */ - _adj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 255.0, 1.0, 10.0, 10.0)); - - /* Slider */ - _slider = sp_color_slider_new (_adj); - gtk_widget_set_tooltip_text (_slider, _("Alpha (opacity)")); - gtk_widget_show (_slider); - -#if GTK_CHECK_VERSION(3,0,0) - #if GTK_CHECK_VERSION(3,12,0) - gtk_widget_set_margin_start(_slider, XPAD); - gtk_widget_set_margin_end(_slider, XPAD); - #else - gtk_widget_set_margin_left(_slider, XPAD); - gtk_widget_set_margin_right(_slider, XPAD); - #endif - gtk_widget_set_margin_top(_slider, YPAD); - gtk_widget_set_margin_bottom(_slider, YPAD); - gtk_widget_set_hexpand(_slider, TRUE); - gtk_widget_set_halign(_slider, GTK_ALIGN_FILL); - gtk_widget_set_valign(_slider, GTK_ALIGN_FILL); - gtk_grid_attach(GTK_GRID(t), _slider, 1, row, 1, 1); -#else - gtk_table_attach(GTK_TABLE (t), _slider, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), GTK_FILL, XPAD, YPAD); -#endif - - sp_color_slider_set_colors (SP_COLOR_SLIDER (_slider), - SP_RGBA32_F_COMPOSE (1.0, 1.0, 1.0, 0.0), - SP_RGBA32_F_COMPOSE (1.0, 1.0, 1.0, 0.5), - SP_RGBA32_F_COMPOSE (1.0, 1.0, 1.0, 1.0)); - - - /* Spinbutton */ - _sbtn = gtk_spin_button_new (GTK_ADJUSTMENT (_adj), 1.0, 0); - gtk_widget_set_tooltip_text (_sbtn, _("Alpha (opacity)")); - sp_dialog_defocus_on_enter (_sbtn); - gtk_label_set_mnemonic_widget (GTK_LABEL(_label), _sbtn); - gtk_widget_show (_sbtn); - -#if GTK_CHECK_VERSION(3,0,0) - #if GTK_CHECK_VERSION(3,12,0) - gtk_widget_set_margin_start(_sbtn, XPAD); - gtk_widget_set_margin_end(_sbtn, XPAD); - #else - gtk_widget_set_margin_left(_sbtn, XPAD); - gtk_widget_set_margin_right(_sbtn, XPAD); - #endif - gtk_widget_set_margin_top(_sbtn, YPAD); - gtk_widget_set_margin_bottom(_sbtn, YPAD); - gtk_widget_set_halign(_sbtn, GTK_ALIGN_CENTER); - gtk_widget_set_valign(_sbtn, GTK_ALIGN_CENTER); - gtk_grid_attach(GTK_GRID(t), _sbtn, 2, row, 1, 1); -#else - gtk_table_attach (GTK_TABLE (t), _sbtn, 2, 3, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, XPAD, YPAD); -#endif - - /* Signals */ - g_signal_connect (G_OBJECT (_adj), "value_changed", - G_CALLBACK (_adjustmentChanged), _csel); - - g_signal_connect (G_OBJECT (_slider), "grabbed", - G_CALLBACK (_sliderGrabbed), _csel); - g_signal_connect (G_OBJECT (_slider), "released", - G_CALLBACK (_sliderReleased), _csel); - g_signal_connect (G_OBJECT (_slider), "changed", - G_CALLBACK (_sliderChanged), _csel); - - g_signal_connect( G_OBJECT(_wheel), "changed", - G_CALLBACK (_wheelChanged), _csel ); -} - -static void sp_color_wheel_selector_dispose(GObject *object) -{ - if (G_OBJECT_CLASS(sp_color_wheel_selector_parent_class)->dispose) - G_OBJECT_CLASS(sp_color_wheel_selector_parent_class)->dispose(object); -} - -static void -sp_color_wheel_selector_show_all (GtkWidget *widget) -{ - gtk_widget_show (widget); -} - -static void sp_color_wheel_selector_hide(GtkWidget *widget) -{ - gtk_widget_hide(widget); -} - -GtkWidget *sp_color_wheel_selector_new() -{ - SPColorWheelSelector *csel = SP_COLOR_WHEEL_SELECTOR(g_object_new (SP_TYPE_COLOR_WHEEL_SELECTOR, NULL)); - - return GTK_WIDGET (csel); -} - -/* Helpers for setting color value */ - -static void preserve_icc(SPColor *color, SPColorWheelSelector *cs){ - ColorSelector* selector = static_cast<ColorSelector*>(SP_COLOR_SELECTOR(cs)->base); - color->icc = selector->getColor().icc ? new SVGICCColor(*selector->getColor().icc) : 0; -} - -void ColorWheelSelector::_colorChanged() -{ -#ifdef DUMP_CHANGE_INFO - g_message("ColorWheelSelector::_colorChanged( this=%p, %f, %f, %f, %f)", this, color.v.c[0], color.v.c[1], color.v.c[2], alpha ); -#endif - _updating = TRUE; - { - float hsv[3] = {0,0,0}; - sp_color_rgb_to_hsv_floatv(hsv, _color.v.c[0], _color.v.c[1], _color.v.c[2]); - gimp_color_wheel_set_color( GIMP_COLOR_WHEEL(_wheel), hsv[0], hsv[1], hsv[2] ); - } - - guint32 start = _color.toRGBA32( 0x00 ); - guint32 mid = _color.toRGBA32( 0x7f ); - guint32 end = _color.toRGBA32( 0xff ); - - sp_color_slider_set_colors(SP_COLOR_SLIDER(_slider), start, mid, end); - - ColorScales::setScaled(_adj, _alpha); - - _updating = FALSE; -} - -void ColorWheelSelector::_adjustmentChanged( GtkAdjustment *adjustment, SPColorWheelSelector *cs ) -{ -// TODO check this. It looks questionable: - // if a value is entered between 0 and 1 exclusive, normalize it to (int) 0..255 or 0..100 - gdouble value = gtk_adjustment_get_value (adjustment); - gdouble upper = gtk_adjustment_get_upper (adjustment); - - if (value > 0.0 && value < 1.0) { - gtk_adjustment_set_value( adjustment, floor (value * upper + 0.5) ); - } - - ColorWheelSelector* wheelSelector = static_cast<ColorWheelSelector*>(SP_COLOR_SELECTOR(cs)->base); - if (wheelSelector->_updating) return; - - wheelSelector->_updating = TRUE; - - preserve_icc(&wheelSelector->_color, cs); - wheelSelector->_updateInternals( wheelSelector->_color, ColorScales::getScaled( wheelSelector->_adj ), wheelSelector->_dragging ); - - wheelSelector->_updating = FALSE; -} - -void ColorWheelSelector::_sliderGrabbed( SPColorSlider *slider, SPColorWheelSelector *cs ) -{ - (void)slider; - ColorWheelSelector* wheelSelector = static_cast<ColorWheelSelector*>(SP_COLOR_SELECTOR(cs)->base); - if (!wheelSelector->_dragging) { - wheelSelector->_dragging = TRUE; - wheelSelector->_grabbed(); - - preserve_icc(&wheelSelector->_color, cs); - wheelSelector->_updateInternals( wheelSelector->_color, ColorScales::getScaled( wheelSelector->_adj ), wheelSelector->_dragging ); - } -} - -void ColorWheelSelector::_sliderReleased( SPColorSlider *slider, SPColorWheelSelector *cs ) -{ - (void)slider; - ColorWheelSelector* wheelSelector = static_cast<ColorWheelSelector*>(SP_COLOR_SELECTOR(cs)->base); - if (wheelSelector->_dragging) { - wheelSelector->_dragging = FALSE; - wheelSelector->_released(); - - preserve_icc(&wheelSelector->_color, cs); - wheelSelector->_updateInternals( wheelSelector->_color, ColorScales::getScaled( wheelSelector->_adj ), wheelSelector->_dragging ); - } -} - -void ColorWheelSelector::_sliderChanged( SPColorSlider *slider, SPColorWheelSelector *cs ) -{ - (void)slider; - ColorWheelSelector* wheelSelector = static_cast<ColorWheelSelector*>(SP_COLOR_SELECTOR(cs)->base); - - preserve_icc(&wheelSelector->_color, cs); - wheelSelector->_updateInternals( wheelSelector->_color, ColorScales::getScaled( wheelSelector->_adj ), wheelSelector->_dragging ); -} - -void ColorWheelSelector::_wheelChanged( GimpColorWheel *wheel, SPColorWheelSelector *cs ) -{ - ColorWheelSelector* wheelSelector = static_cast<ColorWheelSelector*>(SP_COLOR_SELECTOR(cs)->base); - - gdouble h = 0; - gdouble s = 0; - gdouble v = 0; - gimp_color_wheel_get_color( wheel, &h, &s, &v ); - - float rgb[3] = {0,0,0}; - sp_color_hsv_to_rgb_floatv (rgb, h, s, v); - - SPColor color(rgb[0], rgb[1], rgb[2]); - - guint32 start = color.toRGBA32( 0x00 ); - guint32 mid = color.toRGBA32( 0x7f ); - guint32 end = color.toRGBA32( 0xff ); - - sp_color_slider_set_colors (SP_COLOR_SLIDER(wheelSelector->_slider), start, mid, end); - - preserve_icc(&color, cs); - wheelSelector->_updateInternals( color, wheelSelector->_alpha, gimp_color_wheel_is_adjusting(wheel) ); -} - - -/* - 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 : diff --git a/src/widgets/sp-color-wheel-selector.h b/src/widgets/sp-color-wheel-selector.h deleted file mode 100644 index 12b060dbe..000000000 --- a/src/widgets/sp-color-wheel-selector.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef SEEN_SP_COLOR_WHEEL_SELECTOR_H -#define SEEN_SP_COLOR_WHEEL_SELECTOR_H - -#include <gtk/gtk.h> - -#include "sp-color-selector.h" - -typedef struct _GimpColorWheel GimpColorWheel; -struct SPColorSlider; -struct SPColorWheelSelector; -struct SPColorWheelSelectorClass; - -class ColorWheelSelector: public ColorSelector -{ -public: - ColorWheelSelector( SPColorSelector* csel ); - virtual ~ColorWheelSelector(); - - virtual void init(); - -protected: - virtual void _colorChanged(); - - static void _adjustmentChanged ( GtkAdjustment *adjustment, SPColorWheelSelector *cs ); - - static void _sliderGrabbed( SPColorSlider *slider, SPColorWheelSelector *cs ); - static void _sliderReleased( SPColorSlider *slider, SPColorWheelSelector *cs ); - static void _sliderChanged( SPColorSlider *slider, SPColorWheelSelector *cs ); - static void _wheelChanged( GimpColorWheel *wheel, SPColorWheelSelector *cs ); - - static void _fooChanged( GtkWidget foo, SPColorWheelSelector *cs ); - - void _recalcColor( gboolean changing ); - - gboolean _updating : 1; - gboolean _dragging : 1; - GtkAdjustment* _adj; // Channel adjustment - GtkWidget* _wheel; - GtkWidget* _slider; - GtkWidget* _sbtn; // Spinbutton - GtkWidget* _label; // Label - -private: - // By default, disallow copy constructor and assignment operator - ColorWheelSelector( const ColorWheelSelector& obj ); - ColorWheelSelector& operator=( const ColorWheelSelector& obj ); -}; - - - -#define SP_TYPE_COLOR_WHEEL_SELECTOR (sp_color_wheel_selector_get_type ()) -#define SP_COLOR_WHEEL_SELECTOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SP_TYPE_COLOR_WHEEL_SELECTOR, SPColorWheelSelector)) -#define SP_COLOR_WHEEL_SELECTOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), SP_TYPE_COLOR_WHEEL_SELECTOR, SPColorWheelSelectorClass)) -#define SP_IS_COLOR_WHEEL_SELECTOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SP_TYPE_COLOR_WHEEL_SELECTOR)) -#define SP_IS_COLOR_WHEEL_SELECTOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SP_TYPE_COLOR_WHEEL_SELECTOR)) - -struct SPColorWheelSelector { - SPColorSelector parent; -}; - -struct SPColorWheelSelectorClass { - SPColorSelectorClass parent_class; -}; - -GType sp_color_wheel_selector_get_type (void); - -GtkWidget *sp_color_wheel_selector_new (void); - - - -#endif // SEEN_SP_COLOR_WHEEL_SELECTOR_H - -/* - 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 : diff --git a/src/widgets/swatch-selector.cpp b/src/widgets/swatch-selector.cpp index 7178ad072..6f2807255 100644 --- a/src/widgets/swatch-selector.cpp +++ b/src/widgets/swatch-selector.cpp @@ -5,11 +5,11 @@ #include "document-undo.h" #include "gradient-chemistry.h" #include "gradient-selector.h" -#include "sp-color-notebook.h" #include "sp-stop.h" #include "svg/css-ostringstream.h" #include "svg/svg-color.h" #include "verbs.h" +#include "ui/widget/color-notebook.h" #include "xml/node.h" namespace Inkscape @@ -20,8 +20,10 @@ namespace Widgets SwatchSelector::SwatchSelector() : Gtk::VBox(), _gsel(0), - _csel(0) + _updating_color(false) { + using Inkscape::UI::Widget::ColorNotebook; + GtkWidget *gsel = sp_gradient_selector_new(); _gsel = SP_GRADIENT_SELECTOR(gsel); g_object_set_data( G_OBJECT(gobj()), "base", this ); @@ -31,27 +33,18 @@ SwatchSelector::SwatchSelector() : pack_start(*Gtk::manage(Glib::wrap(gsel))); + Gtk::Widget *color_selector = Gtk::manage(new ColorNotebook(_selected_color)); + color_selector->show(); + pack_start(*color_selector); - GtkWidget *csel = sp_color_selector_new( SP_TYPE_COLOR_NOTEBOOK ); - _csel = SP_COLOR_SELECTOR(csel); - Gtk::Widget *wrappedCSel = Glib::wrap(csel); - wrappedCSel->show(); - //gtk_widget_show(csel); - - - GObject *obj = G_OBJECT(csel); - - g_signal_connect(obj, "grabbed", G_CALLBACK(_grabbedCb), this); - g_signal_connect(obj, "dragged", G_CALLBACK(_draggedCb), this); - g_signal_connect(obj, "released", G_CALLBACK(_releasedCb), this); - g_signal_connect(obj, "changed", G_CALLBACK(_changedCb), this); - - pack_start(*Gtk::manage(wrappedCSel)); + _selected_color.signal_grabbed.connect(sigc::mem_fun(this, &SwatchSelector::_grabbedCb)); + _selected_color.signal_dragged.connect(sigc::mem_fun(this, &SwatchSelector::_draggedCb)); + _selected_color.signal_released.connect(sigc::mem_fun(this, &SwatchSelector::_releasedCb)); + _selected_color.signal_changed.connect(sigc::mem_fun(this, &SwatchSelector::_changedCb)); } SwatchSelector::~SwatchSelector() { - _csel = 0; // dtor should be handled by Gtk::manage() _gsel = 0; } @@ -60,13 +53,13 @@ SPGradientSelector *SwatchSelector::getGradientSelector() return _gsel; } -void SwatchSelector::_grabbedCb(SPColorSelector * /*csel*/, void * /*data*/) +void SwatchSelector::_grabbedCb() { } -void SwatchSelector::_draggedCb(SPColorSelector * /*csel*/, void *data) +void SwatchSelector::_draggedCb() { - if (data) { + // if (data) { //SwatchSelector *swsel = reinterpret_cast<SwatchSelector*>(data); // TODO might have to block cycles @@ -92,50 +85,46 @@ void SwatchSelector::_draggedCb(SPColorSelector * /*csel*/, void *data) } } */ - } + // } } -void SwatchSelector::_releasedCb(SPColorSelector * /*csel*/, void * /*data*/) +void SwatchSelector::_releasedCb() { } -void SwatchSelector::_changedCb(SPColorSelector */*csel*/, void *data) +void SwatchSelector::_changedCb() { - if (data) { - SwatchSelector *swsel = reinterpret_cast<SwatchSelector*>(data); + if (_updating_color) { + return; + } + // TODO might have to block cycles + + if (_gsel && _gsel->getVector()) { + SPGradient *gradient = _gsel->getVector(); + SPGradient *ngr = sp_gradient_ensure_vector_normalized(gradient); + if (ngr != gradient) { + /* Our master gradient has changed */ + // TODO replace with proper - sp_gradient_vector_widget_load_gradient(GTK_WIDGET(swsel->_gsel), ngr); + } - // TODO might have to block cycles + ngr->ensureVector(); - if (swsel->_gsel && swsel->_gsel->getVector()) { - SPGradient *gradient = swsel->_gsel->getVector(); - SPGradient *ngr = sp_gradient_ensure_vector_normalized(gradient); - if (ngr != gradient) { - /* Our master gradient has changed */ - // TODO replace with proper - sp_gradient_vector_widget_load_gradient(GTK_WIDGET(swsel->_gsel), ngr); - } - ngr->ensureVector(); + SPStop* stop = ngr->getFirstStop(); + if (stop) { + SPColor color = _selected_color.color(); + gfloat alpha = _selected_color.alpha(); + guint32 rgb = color.toRGBA32( 0x00 ); + // TODO replace with generic shared code that also handles icc-color + Inkscape::CSSOStringStream os; + gchar c[64]; + sp_svg_write_color(c, sizeof(c), rgb); + os << "stop-color:" << c << ";stop-opacity:" << static_cast<gdouble>(alpha) <<";"; + stop->getRepr()->setAttribute("style", os.str().c_str()); - SPStop* stop = ngr->getFirstStop(); - if (stop) { - SPColor color; - float alpha = 0; - guint32 rgb = 0; - - swsel->_csel->base->getColorAlpha( color, alpha ); - rgb = color.toRGBA32( 0x00 ); - - // TODO replace with generic shared code that also handles icc-color - Inkscape::CSSOStringStream os; - gchar c[64]; - sp_svg_write_color(c, sizeof(c), rgb); - os << "stop-color:" << c << ";stop-opacity:" << static_cast<gdouble>(alpha) <<";"; - stop->getRepr()->setAttribute("style", os.str().c_str()); - - DocumentUndo::done(ngr->document, SP_VERB_CONTEXT_GRADIENT, - _("Change swatch color")); - } + DocumentUndo::done(ngr->document, SP_VERB_CONTEXT_GRADIENT, + _("Change swatch color")); } } } @@ -173,11 +162,10 @@ void SwatchSelector::setVector(SPDocument */*doc*/, SPGradient *vector) SPStop* stop = vector->getFirstStop(); guint32 const colorVal = stop->get_rgba32(); - _csel->base->setAlpha(SP_RGBA32_A_F(colorVal)); - SPColor color( SP_RGBA32_R_F(colorVal), SP_RGBA32_G_F(colorVal), SP_RGBA32_B_F(colorVal) ); - // set its color, from the stored array - _csel->base->setColor( color ); - gtk_widget_show_all( GTK_WIDGET(_csel) ); + _updating_color = true; + _selected_color.setValue(colorVal); + _updating_color = false; + // gtk_widget_show_all( GTK_WIDGET(_csel) ); } else { //gtk_widget_hide( GTK_WIDGET(_csel) ); } diff --git a/src/widgets/swatch-selector.h b/src/widgets/swatch-selector.h index 4b7aa483f..16a8cfac8 100644 --- a/src/widgets/swatch-selector.h +++ b/src/widgets/swatch-selector.h @@ -2,6 +2,7 @@ #define SEEN_SP_SWATCH_SELECTOR_H #include <gtkmm/box.h> +#include "ui/selected-color.h" class SPDocument; class SPGradient; @@ -29,13 +30,14 @@ public: SPGradientSelector *getGradientSelector(); private: - static void _grabbedCb(SPColorSelector *csel, void *data); - static void _draggedCb(SPColorSelector *csel, void *data); - static void _releasedCb(SPColorSelector *csel, void *data); - static void _changedCb(SPColorSelector *csel, void *data); + void _grabbedCb(); + void _draggedCb(); + void _releasedCb(); + void _changedCb(); SPGradientSelector *_gsel; - SPColorSelector *_csel; + Inkscape::UI::SelectedColor _selected_color; + bool _updating_color; }; |
