Back to index

scribus-ng  1.3.4.dfsg+svn20071115
charstyle.cpp
Go to the documentation of this file.
00001 /*
00002  For general Scribus (>=1.3.2) copyright and licensing information please refer
00003  to the COPYING file provided with the program. Following this notice may exist
00004  a copyright and/or license notice that predates the release of Scribus 1.3.2
00005  for which a new license (GPL+exception) is in place.
00006  */
00007 
00008 
00009 #include <qvaluelist.h>
00010 #include <qobject.h>
00011 #include "sctextstruct.h"
00012 #include "scfonts.h"
00013 #include "resourcecollection.h"
00014 
00015 #include "styles/style.h"
00016 #include "charstyle.h"
00017 #include "desaxe/saxiohelper.h"
00018 #include "desaxe/simple_actions.h"
00019 #include "prefsmanager.h"
00020 
00021 StyleFlag& StyleFlag::operator&= (const StyleFlag& right){        
00022        int result = static_cast<int>(value) & static_cast<int>(right.value);        
00023        value = static_cast<StyleFlagValue>(result);
00024        return *this;
00025 }
00026 
00027 StyleFlag& StyleFlag::operator|= (const StyleFlag& right)
00028 {
00029        int result = static_cast<int>(value) | static_cast<int>(right.value);
00030        value = static_cast<StyleFlagValue>(result);
00031        return *this;
00032 }
00033 
00034 StyleFlag StyleFlag::operator& (const StyleFlag& right)
00035 {
00036        int val = static_cast<int>(value) & static_cast<int>(right.value);
00037        StyleFlag result(static_cast<StyleFlagValue>(val)); 
00038        return result;
00039 }
00040 
00041 StyleFlag StyleFlag::operator& (int right)
00042 {
00043        int val = static_cast<int>(value) & right;
00044        StyleFlag result(static_cast<StyleFlagValue>(val)); 
00045        return result;
00046 }
00047 
00048 StyleFlag StyleFlag::operator| (const StyleFlag& right)
00049 {        
00050        int val = static_cast<int>(value) | static_cast<int>(right.value);
00051        StyleFlag result(static_cast<StyleFlagValue>(val)); 
00052        return result;
00053 }
00054 
00055 StyleFlag StyleFlag::operator^ (const StyleFlag& right)
00056 {
00057        int val = static_cast<int>(value) ^ static_cast<int>(right.value);
00058        StyleFlag result(static_cast<StyleFlagValue>(val)); 
00059        return result;
00060 }
00061 
00062 StyleFlag StyleFlag::operator^  (int right)
00063 {
00064        int val = static_cast<int>(value) ^ right;
00065        StyleFlag result(static_cast<StyleFlagValue>(val)); 
00066        return result;
00067 }
00068 
00069 StyleFlag StyleFlag::operator~ ()
00070 {
00071        int val = ~ static_cast<int>(value);
00072        StyleFlag result(static_cast<StyleFlagValue>(val)); 
00073        return result;
00074 }
00075 
00076 bool StyleFlag::operator== (const StyleFlag& right) const
00077 {        
00078        int result = static_cast<int>( (value ^ right.value) & ScStyle_UserStyles);
00079        return (result == 0);
00080 }
00081 
00082 bool StyleFlag::operator== (const StyleFlagValue right) const
00083 {
00084        int result = static_cast<int>( (value ^ right) & ScStyle_UserStyles);
00085        return (result == 0);
00086 }
00087 
00088 bool StyleFlag::operator== (int right) const
00089 {
00090        int result = static_cast<int>( (value ^ right) & ScStyle_UserStyles);
00091        return (result == 0);
00092 }
00093 
00094 bool StyleFlag::operator!= (const StyleFlag& right) const
00095 {
00096        return !(*this==right);
00097 }
00098 
00099 bool StyleFlag::operator!= (const StyleFlagValue right) const
00100 {
00101        return !(*this==right);
00102 }
00103 
00104 
00105 
00106 void CharStyle::applyCharStyle(const CharStyle & other)
00107 {
00108        Style::applyStyle(other);
00109 #define ATTRDEF(attr_TYPE, attr_GETTER, attr_NAME, attr_DEFAULT) \
00110        if (! other.inh_##attr_NAME) \
00111               set##attr_NAME(other.m_##attr_NAME);
00112 #include "charstyle.attrdefs.cxx"
00113 #undef ATTRDEF
00114        updateFeatures();
00115 }
00116 
00117 
00118 void CharStyle::eraseCharStyle(const CharStyle & other)
00119 {
00120        other.validate();
00121        Style::eraseStyle(other);
00122 #define ATTRDEF(attr_TYPE, attr_GETTER, attr_NAME, attr_DEFAULT) \
00123        if (!inh_##attr_NAME && m_##attr_NAME == other.m_##attr_NAME) \
00124               reset##attr_NAME();
00125 #include "charstyle.attrdefs.cxx"
00126 #undef ATTRDEF
00127        updateFeatures();
00128 }
00129 
00130 bool CharStyle::equiv(const Style & other) const
00131 {
00132        other.validate();
00133        const CharStyle * oth = dynamic_cast<const CharStyle*> ( & other );
00134        return  oth &&
00135               parent() == oth->parent() 
00136 #define ATTRDEF(attr_TYPE, attr_GETTER, attr_NAME, attr_DEFAULT) \
00137               && (inh_##attr_NAME == oth->inh_##attr_NAME) \
00138               && (inh_##attr_NAME || m_##attr_NAME == oth->m_##attr_NAME)
00139 #include "charstyle.attrdefs.cxx"
00140 #undef ATTRDEF
00141               ;      
00142 }
00143 
00144 
00145 QString CharStyle::displayName() const
00146 {
00147        if ( hasName() || !hasParent() || ! m_context)
00148               return name();
00149 //     else if ( inheritsAll() )
00150 //            return parent()->displayName();
00151        else 
00152               return parentStyle()->displayName() + "+";
00153 }
00154 
00155 
00156 
00157 QString CharStyle::asString() const
00158 {
00159        QString result;
00160        if ( !inh_Font )
00161               result += QObject::tr("font %1 ").arg(font().scName());
00162        if ( !inh_FontSize )
00163               result += QObject::tr("size %1 ").arg(fontSize());
00164        if ( !inh_Features )
00165               result += QObject::tr("+style ");
00166        if ( !inh_StrokeColor  ||  !inh_StrokeShade  ||  !inh_FillColor || !inh_FillShade )
00167               result += QObject::tr("+color ");
00168        if ( !inh_UnderlineWidth  ||  !inh_UnderlineOffset )
00169               result += underlineWidth() > 0 ? QObject::tr("+underline ") : QObject::tr("-underline ");
00170        if ( !inh_StrikethruWidth || !inh_StrikethruOffset )
00171               result += strikethruWidth() > 0 ? QObject::tr("+strikeout ") : QObject::tr("-strikeout ");
00172        if ( !inh_ShadowXOffset || !inh_ShadowYOffset )
00173               result += shadowXOffset() != 0 || shadowYOffset() != 0 ? QObject::tr("+shadow ") : QObject::tr("-shadow ");
00174        if ( !inh_OutlineWidth )
00175               result += outlineWidth() > 0 ? QObject::tr("+outline ") : QObject::tr("-outline ");
00176        if ( !inh_Tracking )
00177               result += tracking() > 0 ? QObject::tr("+tracking %1 ").arg(tracking()) : QObject::tr("-tracking ");
00178        if ( !inh_BaselineOffset )
00179               result += QObject::tr("+baseline %1 ").arg(baselineOffset());
00180        if ( !inh_ScaleH || !inh_ScaleV )
00181               result += QObject::tr("+stretch ");
00182        if ( hasParent() )
00183               result += QObject::tr("parent= %1").arg(parent());
00184        return result.stripWhiteSpace();
00185 }
00186 
00187 
00188 void CharStyle::update(const StyleContext* context)
00189 {
00190        Style::update(context);
00191        const CharStyle * oth = dynamic_cast<const CharStyle*> ( parentStyle() );
00192        if (oth) {
00193 #define ATTRDEF(attr_TYPE, attr_GETTER, attr_NAME, attr_DEFAULT) \
00194               if (inh_##attr_NAME) \
00195                      m_##attr_NAME = oth->attr_GETTER();
00196 #include "charstyle.attrdefs.cxx"
00197 #undef ATTRDEF
00198        }
00199        updateFeatures();
00200 }
00201 
00202 
00203 
00204 const QString CharStyle::INHERIT = "inherit";
00205 const QString CharStyle::BOLD = "bold";
00206 const QString CharStyle::ITALIC = "italic";
00207 const QString CharStyle::UNDERLINE = "underline";
00208 const QString CharStyle::UNDERLINEWORDS = "underlinewords";
00209 const QString CharStyle::STRIKETHROUGH = "strike";
00210 const QString CharStyle::SUPERSCRIPT = "superscript";
00211 const QString CharStyle::SUBSCRIPT = "subscript";
00212 const QString CharStyle::OUTLINE = "outline";
00213 const QString CharStyle::SHADOWED = "shadowed";
00214 const QString CharStyle::ALLCAPS = "allcaps";
00215 const QString CharStyle::SMALLCAPS = "smallcaps";
00216 // This is for loading legacy docs only. Scribus 1.3.4 should write smart hyphens in another way 
00217 static const QString SHYPHEN = "shyphen";
00218 
00219 
00220 QStringList StyleFlag::featureList() const
00221 {
00222        QStringList result(CharStyle::INHERIT);
00223        if (*this & ScStyle_Underline)
00224               result << CharStyle::UNDERLINE;
00225        if (*this & ScStyle_UnderlineWords)
00226               result << CharStyle::UNDERLINEWORDS;
00227        if (*this & ScStyle_Strikethrough)
00228               result << CharStyle::STRIKETHROUGH;
00229        if (*this & ScStyle_Superscript)
00230               result << CharStyle::SUPERSCRIPT;
00231        if (*this & ScStyle_Subscript)
00232               result << CharStyle::SUBSCRIPT;
00233        if (*this & ScStyle_Outline)
00234               result << CharStyle::OUTLINE;
00235        if (*this & ScStyle_Shadowed)
00236               result << CharStyle::SHADOWED;
00237        if (*this & ScStyle_AllCaps)
00238               result << CharStyle::ALLCAPS;
00239        if (*this & ScStyle_SmallCaps)
00240               result << CharStyle::SMALLCAPS;
00241        if (*this & ScStyle_HyphenationPossible)
00242               result << SHYPHEN;
00243        return result;
00244 }
00245 
00246 
00247 void CharStyle::updateFeatures()
00248 {
00249        m_Effects &= ~ScStyle_UserStyles;
00250        runFeatures(m_Features, dynamic_cast<const CharStyle*>(parentStyle()));
00251 /* need to access global fontlist :-/
00252        if (!font().name().endsWith(fontVariant()))
00253        {
00254               m_font = ScFonts.instance().findFont(font().family() + fontVariant());
00255        }
00256  */
00257 }
00258 
00259 
00260 void CharStyle::runFeatures(const QStringList& featureList, const CharStyle* parent)
00261 {
00262        QStringList::ConstIterator it;
00263        for (it = featureList.begin(); it != featureList.end(); ++it)
00264        {
00265               QString feature = *it;
00266               if (feature == INHERIT)
00267               {
00268                      if (parent)
00269                             runFeatures(parent->features(), dynamic_cast<const CharStyle*>(parent->parentStyle()));
00270               }
00271               else if (feature == BOLD)
00272               {
00273                      // select bolder font
00274               }
00275               else if (feature == ITALIC)
00276               {
00277                      // select italic font
00278               }
00279               else if (feature == UNDERLINE)
00280               {
00281                      m_Effects |= ScStyle_Underline;
00282               }
00283               else if (feature == UNDERLINEWORDS)
00284               {
00285                      m_Effects |= ScStyle_UnderlineWords;
00286               }
00287               else if (feature == STRIKETHROUGH)
00288               {
00289                      m_Effects |= ScStyle_Strikethrough;
00290               }
00291               else if (feature == SUPERSCRIPT)
00292               {
00293                      m_Effects |= ScStyle_Superscript;
00294               }
00295               else if (feature == SUBSCRIPT)
00296               {
00297                      m_Effects |= ScStyle_Subscript;
00298               }
00299               else if (feature == OUTLINE)
00300               {
00301                      m_Effects |= ScStyle_Outline;
00302               }
00303               else if (feature == SHADOWED)
00304               {
00305                      m_Effects |= ScStyle_Shadowed;
00306               }
00307               else if (feature == ALLCAPS)
00308               {
00309                      m_Effects |= ScStyle_AllCaps;
00310               }
00311               else if (feature == SMALLCAPS)
00312               {
00313                      m_Effects |= ScStyle_SmallCaps;
00314               }
00315               else if (feature == SHYPHEN)
00316               {
00317                      m_Effects |= ScStyle_HyphenationPossible;
00318               }
00319               else if (feature.startsWith("-"))
00320               {
00321                      QString no_feature = feature.mid(1);
00322                      if (no_feature == BOLD)
00323                      {
00324                             // deselect bolder font
00325                      }
00326                      else if (no_feature == ITALIC)
00327                      {
00328                             // deselect italic font
00329                      }
00330                      else if (no_feature == UNDERLINE)
00331                      {
00332                             m_Effects &= ~ScStyle_Underline;
00333                      }
00334                      else if (no_feature == UNDERLINEWORDS)
00335                      {
00336                             m_Effects &= ~ScStyle_UnderlineWords;
00337                      }
00338                      else if (no_feature == STRIKETHROUGH)
00339                      {
00340                             m_Effects &= ~ScStyle_Strikethrough;
00341                      }
00342                      else if (no_feature == SUPERSCRIPT)
00343                      {
00344                             m_Effects &= ~ScStyle_Superscript;
00345                      }
00346                      else if (no_feature == SUBSCRIPT)
00347                      {
00348                             m_Effects &= ~ScStyle_Subscript;
00349                      }
00350                      else if (no_feature == OUTLINE)
00351                      {
00352                             m_Effects &= ~ScStyle_Outline;
00353                      }
00354                      else if (no_feature == SHADOWED)
00355                      {
00356                             m_Effects &= ~ScStyle_Shadowed;
00357                      }
00358                      else if (no_feature == ALLCAPS)
00359                      {
00360                             m_Effects &= ~ScStyle_AllCaps;
00361                      }
00362                      else if (no_feature == SMALLCAPS)
00363                      {
00364                             m_Effects &= ~ScStyle_SmallCaps;
00365                      }
00366                      else {
00367                             qDebug("CharStyle: unknown feature: %s", feature.ascii());
00368                      }
00369               }
00370               else {
00371                      qDebug("CharStyle: unknown feature: %s", feature.ascii());
00372               }
00373               
00374        }
00375 }
00376 
00377 
00378 
00379 void CharStyle::setStyle(const CharStyle& other) 
00380 {
00381        other.validate();
00382        setParent(other.parent());
00383        m_contextversion = -1; 
00384 #define ATTRDEF(attr_TYPE, attr_GETTER, attr_NAME, attr_DEFAULT) \
00385        inh_##attr_NAME = other.inh_##attr_NAME; \
00386        m_##attr_NAME = other.m_##attr_NAME;
00387 #include "charstyle.attrdefs.cxx"
00388 #undef ATTRDEF
00389        updateFeatures();
00390 }
00391 
00392 void CharStyle::getNamedResources(ResourceCollection& lists) const
00393 {
00394        for (const Style* sty = parentStyle(); sty != NULL; sty = sty->parentStyle())
00395               lists.collectCharStyle(sty->name());
00396        lists.collectColor(fillColor());
00397        lists.collectColor(strokeColor());
00398        lists.collectFont(font().scName());
00399 }
00400 
00401 
00402 void CharStyle::replaceNamedResources(ResourceCollection& newNames)
00403 {
00404        QMap<QString,QString>::ConstIterator it;
00405        
00406        if (!inh_FillColor && (it = newNames.colors().find(fillColor())) != newNames.colors().end())
00407               setFillColor(it.data()); 
00408                                                           
00409        if (!inh_StrokeColor && (it = newNames.colors().find(strokeColor())) != newNames.colors().end())
00410               setStrokeColor(it.data());
00411 
00412        if (hasParent() && (it = newNames.charStyles().find(parent())) != newNames.charStyles().end())
00413               setParent(it.data());
00414        
00415        if (!inh_Font && (it = newNames.fonts().find(font().scName())) != newNames.fonts().end())
00416               setFont(newNames.availableFonts->findFont(it.data(), NULL));
00417        updateFeatures();
00418 }
00419                                                         
00420                                                           /*
00421 bool CharStyle::definesAll() const
00422 {
00423        return definesLineSpacing() && 
00424        definesLeftMargin() && 
00425        definesRightMargin() && 
00426        definesFirstIndent() &&
00427        definesAlignment() && 
00428        definesGapBefore()  &&
00429        definesLineSpacingMode()  && 
00430        definesGapAfter()  && 
00431        definesHasDropCap() && 
00432        definesDropCapOffset() && 
00433        definesDropCapLines() && 
00434        definesUseBaselineGrid() && 
00435        charStyle().definesAll() ;
00436        
00437 }
00438 
00439 // equiv. to "*this == CharStyle()"
00440 bool CharStyle::inheritsAll() const
00441 {
00442        return inheritsLineSpacing() && 
00443        inheritsLeftMargin() && 
00444        inheritsRightMargin() && 
00445        inheritsFirstIndent() &&
00446        inheritsAlignment() && 
00447        inheritsGapBefore()  &&
00448        inheritsLineSpacingMode()  && 
00449        inheritsGapAfter()  && 
00450        inheritsHasDropCap() && 
00451        inheritsDropCapOffset() && 
00452        inheritsDropCapLines() && 
00453        inheritsUseBaselineGrid() && 
00454        charStyle().inheritsAll() ;
00455 }
00456 */
00457 
00458 
00459 Xml_string toXMLString(StyleFlag val)
00460 {
00461        return toXMLString(static_cast<unsigned int>(val & ScStyle_UserStyles));
00462 }
00463 
00464 
00465 void CharStyle::saxx(SaxHandler& handler, const Xml_string& elemtag) const
00466 {
00467        Xml_attr att;
00468        Style::saxxAttributes(att);
00469 #define ATTRDEF(attr_TYPE, attr_GETTER, attr_NAME, attr_DEFAULT) \
00470        if (!inh_##attr_NAME) \
00471               att.insert(# attr_NAME, toXMLString(m_##attr_NAME));
00472 #include "charstyle.attrdefs.cxx"
00473 #undef ATTRDEF
00474        if (!name().isEmpty())
00475               att["id"] = mkXMLName(elemtag + name());
00476        handler.begin(elemtag, att);
00477 //     if (hasParent() && parentStyle())
00478 //            parentStyle()->saxx(handler);      
00479        handler.end(elemtag);
00480 }
00481 
00482 
00483 
00484 template<>
00485 StyleFlag parse<StyleFlag>(const Xml_string& str)
00486 {
00487        return StyleFlag(parseInt(str));
00488 }
00489 
00490 template<>
00491 ScFace parse<ScFace>(const Xml_string& str)
00492 {
00493        // FIXME: enable font substitution here
00494        return PrefsManager::instance()->appPrefs.AvailFonts[str];
00495 }
00496 
00497 
00498 using namespace desaxe;
00499 
00500 
00501 const Xml_string CharStyle::saxxDefaultElem("charstyle");
00502 
00503 void CharStyle::desaxeRules(const Xml_string& prefixPattern, Digester& ruleset, Xml_string elemtag)
00504 {
00505        Xml_string stylePrefix(Digester::concat(prefixPattern, elemtag));
00506        ruleset.addRule(stylePrefix, Factory<CharStyle>());
00507        ruleset.addRule(stylePrefix, IdRef<CharStyle>());
00508        Style::desaxeRules<CharStyle>(prefixPattern, ruleset, elemtag);
00509 #define ATTRDEF(attr_TYPE, attr_GETTER, attr_NAME, attr_DEFAULT) \
00510        ruleset.addRule(stylePrefix, SetAttributeWithConversion<CharStyle, attr_TYPE> ( & CharStyle::set##attr_NAME,  # attr_NAME, &parse<attr_TYPE> ));
00511 #include "charstyle.attrdefs.cxx"
00512 #undef ATTRDEF              
00513 }