void WrdStyleSheet::GetStyleList(ChUINT2 in_unParagraphStyleIndex, ChVector<ChUINT2>& vecStyles) const { ChUINT2 unStyleIndex = in_unParagraphStyleIndex; while (unStyleIndex != 0x0FFF) { vecStyles.push_back(unStyleIndex); const WrdStyle& style = getStyle(unStyleIndex); unStyleIndex = style.getBaseStyleIndex(); } if (vecStyles.size() == 0 || vecStyles[vecStyles.size() - 1] != 0) vecStyles.push_back(0); }
void XlChartPlotSeries::classifySeries (XlChartBinaryReader& in_reader) { //NOTE! modifies m_uCurrentIndex. // enum {undef = -2, aux, std, trend, xPos, xNeg, yPos, yNeg} type = undef; ChAutoPtr<XlHeader> pHeader(ChNEW XlHeader()); ChSINT4 lPos = in_reader.getStream()->getPos(); if ( in_reader.nextSibling(*pHeader) ) { in_reader.getStream()->seek( pHeader->getLength() + XlRecord::HDR_SIZE, SsrwOO_CUR ); // Open container and parse subordinates. // Find out about series type, // also get main series group index or pick up aux series parent while parsing. in_reader.m_pParser->getHeader( *pHeader, in_reader.getSheetVersion() ); if ( pHeader->getId() == XlChartBegin::ID ) { ChSINT2 unAuxParentInd = -1; ChVector<SeriesDescription>* pList = NULL; // tells about group type // when completed while ( in_reader.nextSibling(*pHeader) ) { switch ( pHeader->getId() ) { case XlChartSerToCrt::ID: //order 1 { ChAutoPtr<XlChartSerToCrt> pSerToCrt( ChNEW XlChartSerToCrt(*pHeader) ); in_reader.getStream()->seek(XlRecord::HDR_SIZE, SsrwOO_CUR); in_reader.m_pParser->visit(*pSerToCrt); if (type == undef) { type = std; pList = ( pSerToCrt->getChartGroup() == 1 )? &m_secondaryGroupSeries : &m_mainGroupSeries; } break; } case XlChartSerParent::ID: //order 1 { ChAutoPtr<XlChartSerParent> pSerParent( ChNEW XlChartSerParent(*pHeader) ); in_reader.getStream()->seek(XlRecord::HDR_SIZE, SsrwOO_CUR); in_reader.m_pParser->visit(*pSerParent); if (type == undef) { type = aux; // this record seems to use 1 based indexes so subtract 1 to get 0 based unAuxParentInd = pSerParent->getSeriesNumber() - 1; } break; } case XlChartSerAuxErrBar::ID: //order 2 { ChAutoPtr<XlChartSerAuxErrBar> pSerErr( ChNEW XlChartSerAuxErrBar(*pHeader) ); in_reader.getStream()->seek(XlRecord::HDR_SIZE, SsrwOO_CUR); in_reader.m_pParser->visit(*pSerErr); if (type == aux) { switch ( pSerErr->getErrorBarType() ) { case EB_XPLUS: { type = xPos; break; } case EB_XMINUS: { type = xNeg; break; } case EB_YPLUS: { type = yPos; break; } case EB_YMINUS: { type = yNeg; break; } } } break; } case XlChartSerAuxTrend::ID: //order 2 // no need to parse yet... if (type == aux) { type = trend; } // no break! // step over the header as we didn't read anything. default: in_reader.getStream()->seek( pHeader->getLength() + XlRecord::HDR_SIZE, SsrwOO_CUR ); break; } } switch (type) { default: // case undef: // incorrect file data case aux: // { break; } case std: // primary series { // standard series are simply appended to their list ChAutoPtr<SeriesDescription> pSeries( ChNEW SeriesDescription() ); pSeries->m_primary.m_lLoc = lPos; pSeries->m_primary.m_unIndex = m_uCurrentIndex; pList->push_back(*pSeries); break; } case trend: // case xPos: // case xNeg: // aux series case yPos: // case yNeg: // { // need to find the parent // ASSUMPTION: parent already exists. If BIFF files define an auxillary // series before the parent series, this assumption is invalid and // the result will be missing auxillary information. //Look in the main axis group first, then in the secondary axis group if (unAuxParentInd >= 0) { ChUINT2 iGroup; for (iGroup = 0; iGroup < 2; iGroup ++) { ChVector<SeriesDescription>* pList = iGroup == 0? &m_mainGroupSeries : &m_secondaryGroupSeries; ChUINT2 iListItem; for (iListItem = 0; iListItem < pList->size(); iListItem ++) { if (pList->at(iListItem).m_primary.m_unIndex == unAuxParentInd) { switch (type) { case trend: { SeriesDesc desc; desc.m_lLoc = lPos; desc.m_unIndex = m_uCurrentIndex; pList->at(iListItem).m_trendlines.push_back(desc); break; } case xPos: pList->at(iListItem).m_ErrorXPos.m_lLoc = lPos; pList->at(iListItem).m_ErrorXPos.m_unIndex = m_uCurrentIndex; break; case xNeg: pList->at(iListItem).m_ErrorXNeg.m_lLoc = lPos; pList->at(iListItem).m_ErrorXNeg.m_unIndex = m_uCurrentIndex; break; case yPos: pList->at(iListItem).m_ErrorYPos.m_lLoc = lPos; pList->at(iListItem).m_ErrorYPos.m_unIndex = m_uCurrentIndex; break; case yNeg: pList->at(iListItem).m_ErrorYNeg.m_lLoc = lPos; pList->at(iListItem).m_ErrorYNeg.m_unIndex = m_uCurrentIndex; break; } iGroup = 2; // break the group loop as we don't need to look in // secondary series if we succeeded. break; // break this list search } } } } break; } } } } m_uCurrentIndex ++; }
ChEXPORT void WrdStyleSheet::resolve(WrdCharacterProperties& io_charProps, ChUINT2 in_unParagraphStyleIndex) const { ChUINT2 unStyleIndex = in_unParagraphStyleIndex; // If the character properties does have the style descriptor overridden, // use that one first. if (io_charProps.isStyleIndexOverridden()) { unStyleIndex = io_charProps.getStyleIndex(); // Design-wise, a more elegant solution is to access the first base style, // and then apply the derived style's properties on top of the base style, // and recursively do this, until lastly, the delta character properties // are applied. However, to do this elegantly requires using recursion, // and also requires the creation of an additional WrdCharacterProperties // structure which contains the base style and the derived style's // merged results. Given the need to minimize stack usage and heap memory, // the alternative is to traverse the style's backwards and apply all // changes directly to the delta set of properties. Thus, we get the style // that the delta references, apply its properties, then get the // base style, and apply its properties, and go upwards to the top-most // style. do { const WrdStyle& style = getStyle(unStyleIndex); const WrdCharacterProperties& styleCharProps = style.getResolvedCharProps(); if (io_charProps.getUseParagraphStylesProperties()) { // If the character properties' says to use the paragraph style's // properties, then we can ignore all the different overrides // currently set, and take the style's character properties instead. // The only thing that is preserved should be the special character. ChUINT2 unSpecialCharacter = io_charProps.getSpecialCharacter(); io_charProps = styleCharProps; io_charProps.setSpecialCharacter(unSpecialCharacter); } else if (styleCharProps.isAnythingOverridden()) { // Only apply the style properties if there is something that has been // overridden. io_charProps.applyBaseProperties(styleCharProps); } unStyleIndex = style.getBaseStyleIndex(); } while (unStyleIndex != 0x0FFF); } // Now apply the paragraph properties's character styling information unStyleIndex = in_unParagraphStyleIndex; // get a base char props WrdCharacterProperties charProps(m_pDefaultStyle->getOrigCharProps()); // get style list ChVector<ChUINT2> vecStyles; GetStyleList(in_unParagraphStyleIndex, vecStyles); // last one should always be 0 for (int i = vecStyles.size() - 1; i >= 0; i--) { unStyleIndex = vecStyles[i]; const WrdStyle& style = getStyle(unStyleIndex); const WrdCharacterProperties& styleCharProps = style.getOrigCharProps(); // Only apply the style properties if there is something that has been overridden. if (styleCharProps.isAnythingOverridden()) { charProps.applyNextProperties(styleCharProps); } } // apply styles we came in with charProps.applyNextProperties(io_charProps); // return io_charProps = charProps; }