Scribus Developer Documentation - API
logo-pen

Scribus Developer Documentation - API

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