diff options
author | Peter Breitenlohner <peb@mppmu.mpg.de> | 2009-03-19 13:59:30 +0000 |
---|---|---|
committer | Peter Breitenlohner <peb@mppmu.mpg.de> | 2009-03-19 13:59:30 +0000 |
commit | 0b7b2c69ec83497d9accab064da0f4ad07662d42 (patch) | |
tree | e8f22a2acecbf3035850f56beb1c8161c53cdf2d /Build/source/libs/graphite/src/segment/XmlTransductionLog.cpp | |
parent | ee507bbd1fc483c58acb33cca25509a4dd81df9b (diff) |
prepare for new build system
git-svn-id: svn://tug.org/texlive/trunk@12429 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/graphite/src/segment/XmlTransductionLog.cpp')
-rw-r--r-- | Build/source/libs/graphite/src/segment/XmlTransductionLog.cpp | 1583 |
1 files changed, 1583 insertions, 0 deletions
diff --git a/Build/source/libs/graphite/src/segment/XmlTransductionLog.cpp b/Build/source/libs/graphite/src/segment/XmlTransductionLog.cpp new file mode 100644 index 00000000000..d0dfcaafbe8 --- /dev/null +++ b/Build/source/libs/graphite/src/segment/XmlTransductionLog.cpp @@ -0,0 +1,1583 @@ +/*--------------------------------------------------------------------*//*:Ignore this sentence. +Copyright (C) 2008 SIL International. All rights reserved. + +Distributable under the terms of either the Common Public License or the +GNU Lesser General Public License, as specified in the LICENSING.txt file. + +File: TransductionLog.cpp +Responsibility: Sharon Correll +Last reviewed: Not yet. + +Description: + Contains the functions for writing a log of the transduction process using an XML format. +----------------------------------------------------------------------------------------------*/ + +//:>******************************************************************************************** +//:> Include files +//:>******************************************************************************************** +#include "Main.h" + +#ifdef _MSC_VER +#pragma hdrstop +#endif + +#include <math.h> + +#undef THIS_FILE +DEFINE_THIS_FILE + +//:End Ignore + +//:>******************************************************************************************** +//:> Forward declarations +//:>******************************************************************************************** + +//:>******************************************************************************************** +//:> Local Constants and static variables +//:>******************************************************************************************** + +namespace gr +{ + +//:>******************************************************************************************** +//:> Methods +//:>******************************************************************************************** + +#define SP_PER_SLOT 7 +#define LEADING_SP 15 +#define MAX_SLOTS 128 + +/*---------------------------------------------------------------------------------------------- + Output a file showing a log of the transduction process and the resulting segment. +----------------------------------------------------------------------------------------------*/ +bool GrTableManager::WriteXmlLog(std::ostream * pstrmLog, + GrCharStream * pchstrm, Segment * psegRet, int cbPrevSegDat, byte * pbPrevSegDat) +{ +#ifdef TRACING + if (!pstrmLog) + return false; + std::ostream & strmOut = *pstrmLog; + WriteXmlLogAux(strmOut, pchstrm, psegRet, cbPrevSegDat, pbPrevSegDat); + return true; +#else + return false; +#endif // TRACING +} + + +bool GrTableManager::WriteXmlAssocLog(std::ostream * pstrmLog, + GrCharStream * pchstrm, Segment * psegRet) +{ +#ifdef TRACING + if (!pstrmLog) + return false; + + std::ostream & strmOut = *pstrmLog; + LogFinalPositions(strmOut); + + LogXmlTagOpen(strmOut, "Mappings", 1, true); + LogXmlTagPostAttrs(strmOut, true); + + //psegRet->LogXmlUnderlyingToSurface(strmOut, this, pchstrm, 2); + //psegRet->LogXmlSurfaceToUnderlying(strmOut, this, 2); + + LogXmlTagClose(strmOut, "Mappings", 1, true); + + strmOut << "\n"; + LogXmlTagClose(strmOut, "GraphiteTraceLog", 0, true); + + return true; +#else + return false; +#endif // TRACING +} + +#ifdef TRACING + +/*---------------------------------------------------------------------------------------------- + Output a file showing a log of the transduction process and the resulting segment. +----------------------------------------------------------------------------------------------*/ +void GrTableManager::WriteXmlLogAux(std::ostream & strmOut, + GrCharStream * pchstrm, Segment * psegRet, + int cbPrevSegDat, byte * pbPrevSegDat) +{ + strmOut + << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + << "<!DOCTYPE GraphiteTraceLog SYSTEM \"GraphiteTraceLog.dtd\">\n" + << "\n"; + + LogXmlTagOpen(strmOut, "GraphiteTraceLog", 0, true); + LogXmlTagPostAttrs(strmOut, true); + strmOut << "\n"; + + LogXmlTagOpen(strmOut, "SegmentRun", 1, true); + LogXmlTagAttr(strmOut, "stringOffset", pchstrm->Min(), 0); + LogXmlTagPostAttrs(strmOut, true); + + if (cbPrevSegDat == 0) + LogXmlUnderlying(strmOut, pchstrm, 0, 2); + else + { + Assert(*(pbPrevSegDat + 4) == 0); // skip offset for first pass + LogXmlUnderlying(strmOut, pchstrm, *(pbPrevSegDat + 3), 2); + } + + //LogXmlPass1Input(strmOut); + + for (int ipass = 0; ipass < m_cpass; ipass++) + { + if (cbPrevSegDat == 0) + LogXmlPass(strmOut, ipass, 0, 2); + else + LogXmlPass(strmOut, ipass, *(pbPrevSegDat + 4 + ipass), 2); + } + + LogXmlTagClose(strmOut, "SegmentRun", 1, true); + strmOut << "\n"; + + // Don't do this until after we've logged the associations. + //LogXmlTagClose(strmOut, "GraphiteTraceLog", 0, true); +} + +/*---------------------------------------------------------------------------------------------- + Write out a log of the underlying input. +----------------------------------------------------------------------------------------------*/ +void GrTableManager::LogXmlUnderlying(std::ostream & strmOut, GrCharStream * pchstrm, + int cchwBackup, size_t nIndent) +{ + LogXmlTagOpen(strmOut, "Input", nIndent, true); + LogXmlTagPostAttrs(strmOut, true); + + LogXmlUnderlyingAux(strmOut, pchstrm, cchwBackup, -1, nIndent, + true, // text + true, // features + true, // color + false, // string offset + false, // ligature components + false); // glyph associations + + LogXmlTagClose(strmOut, "Input", nIndent, true); +} + +void GrTableManager::LogXmlUnderlyingAux(std::ostream & strmOut, GrCharStream * pchstrm, + int cch32Backup, int cch32Lim, size_t nIndent, + bool fLogText, bool fLogFeatures, bool fLogColor, bool fLogStrOff, bool fLogLig, bool fLogGlyphs) +{ + int rgnChars[MAX_SLOTS]; + bool rgfNewRun[MAX_SLOTS]; + std::fill_n(rgfNewRun, MAX_SLOTS, false); + GrFeatureValues rgfval[MAX_SLOTS]; + int cchwMaxRawChars; + + int cch32 = pchstrm->GetLogData(this, rgnChars, rgfNewRun, rgfval, + cch32Backup, &cchwMaxRawChars); + cch32 = min(cch32, MAX_SLOTS); + if (cch32Lim > -1) + cch32 = min(cch32Lim, cch32); + + int ichw; + + // For UTF-8 and surrogate representation: + int rgchwChars1[MAX_SLOTS]; + utf16 rgchwChars2[MAX_SLOTS]; + utf16 rgchwChars3[MAX_SLOTS]; + utf16 rgchwChars4[MAX_SLOTS]; + utf16 rgchwChars5[MAX_SLOTS]; + utf16 rgchwChars6[MAX_SLOTS]; + utf16 rgiRawString[MAX_SLOTS]; // indices from underlying slots to text-source chars (0-based) + + int rgichwRaw[MAX_SLOTS]; // index of input char with in the given UTF32, 1-based + + if (cchwMaxRawChars > 1) + { + cchwMaxRawChars = min(cchwMaxRawChars, 6); // max of 6 raw (UTF-8 or UTF-16) chars per slot + pchstrm->GetLogDataRaw(this, cch32, cch32Backup, cchwMaxRawChars, + rgchwChars1, rgchwChars2, rgchwChars3, rgchwChars4, rgchwChars5, rgchwChars6, + rgichwRaw); + } + else + { + for (ichw = 0; ichw < cch32; ichw++) + { + rgichwRaw[ichw] = 1; + rgchwChars1[ichw] = rgnChars[ichw]; + rgchwChars2[ichw] = 0; + rgchwChars3[ichw] = 0; + rgchwChars4[ichw] = 0; + rgchwChars5[ichw] = 0; + rgchwChars6[ichw] = 0; + } + } + + int ichUtf32 = 0; + ichw = 0; + while (ichUtf32 < cch32) + { + if (rgichwRaw[ichw] == 1) + { + rgiRawString[ichUtf32++] = (utf16)ichw; + } + ichw++; + } + + int ichwFeat = 0; + for (ichw = 0; ichw < cch32; ichw++) + { + if (rgfNewRun[ichw]) + ichwFeat = ichw; // because rgfval only saves features for first of run + + // See if there are any features. + bool fFeatures = false; + size_t ifeat; + for (ifeat = 0; fLogFeatures && ifeat < kMaxFeatures; ifeat++) + { + if (rgfval[ichwFeat].FeatureValue(ifeat) != 0) + { + fFeatures = true; + break; + } + } + + bool fContent = fFeatures; + + LogXmlTagOpen(strmOut, "Char", nIndent+1, fContent); + + LogXmlTagAttr(strmOut, "index", rgiRawString[ichw] - cch32Backup, 0); + LogXmlTagAttrHex(strmOut, "usv", rgnChars[ichw], 0); + + if (fLogText) + { + char rgch[20]; + rgch[0] = (char)rgnChars[ichw]; + rgch[1] = 0; + if (rgnChars[ichw] < 0x0100 && rgchwChars2[ichw] == 0) // ANSI + LogXmlTagAttr(strmOut, "text", rgch); + else if (rgnChars[ichw] == knLRM) + LogXmlTagAttr(strmOut, "text", "<LRM>"); + else if (rgnChars[ichw] == knRLM) + LogXmlTagAttr(strmOut, "text", "<RLM>"); + else if (rgnChars[ichw] == knLRO) + LogXmlTagAttr(strmOut, "text", "<LRO>"); + else if (rgnChars[ichw] == knRLO) + LogXmlTagAttr(strmOut, "text", "<RLO>"); + else if (rgnChars[ichw] == knLRE) + LogXmlTagAttr(strmOut, "text", "<LRE>"); + else if (rgnChars[ichw] == knRLE) + LogXmlTagAttr(strmOut, "text", "<RLE>"); + else if (rgnChars[ichw] == knPDF) + LogXmlTagAttr(strmOut, "text", "<PDF>"); + } + + if (fLogStrOff) + LogXmlTagAttr(strmOut, "stringOffset", pchstrm->Min() + rgiRawString[ichw] - cch32Backup, 0); + + if (rgchwChars2[ichw] != 0) + { + std::string strHex = HexString(rgchwChars1[ichw], rgchwChars2[ichw], rgchwChars3[ichw], + rgchwChars4[ichw], rgchwChars5[ichw], rgchwChars6[ichw]); + if (pchstrm->TextSrc()->utfEncodingForm() == kutf8) + LogXmlTagAttr(strmOut, "textSourceUtf8", strHex.c_str()); + else + LogXmlTagAttr(strmOut, "textSourceUtf16", strHex.c_str()); + } + + if (fLogColor) + { + IColorTextSource * tscolor = dynamic_cast<IColorTextSource *>(pchstrm->TextSrc()); + if (tscolor) + { + int clrFore, clrBack; + tscolor->getColors(ichw, &clrFore, &clrBack); + LogXmlTagColor(strmOut, "color", clrFore, false); + LogXmlTagColor(strmOut, "background", clrBack, true); + } + } + + if (fLogLig) + { + + } + +//if (fLogLig || fLogGlyphs) +//{ +// size_t cassocs = 0; +// int fLigs = false; +// int ichw; +// for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) +// { +// if (m_prgpvisloutAssocs[ichw]) +// cassocs = max(cassocs, m_prgpvisloutAssocs[ichw]->size()); +// if (m_prgisloutLigature[ichw] != kNegInfinity) +// fLigs = true; +// } +//} + + LogXmlTagPostAttrs(strmOut, fContent); + + if (fLogFeatures) + { + for (ifeat = 0; ifeat < kMaxFeatures; ifeat++) + { + if (rgfval[ichwFeat].FeatureValue(ifeat) != 0) + { + GrFeature * pfeat = Feature(ifeat); + + LogXmlTagOpen(strmOut, "Feature", nIndent+2, false); + LogXmlTagAttr(strmOut, "id", pfeat->ID()); + LogXmlTagAttr(strmOut, "value", rgfval[ichwFeat].FeatureValue(ifeat)); + //LogXmlTagPostAttrs(strmOut, false); + LogXmlTagClose(strmOut, "Feature", nIndent+1, false); + } + } + } + + if (fLogGlyphs) + { + } + + LogXmlTagClose(strmOut, "Char", nIndent+1, fContent); + } +} + +/*---------------------------------------------------------------------------------------------- + Output the the results of pass. +----------------------------------------------------------------------------------------------*/ +void GrTableManager::LogXmlPass(std::ostream & strmOut, int ipass, int cslotSkipped, int nIndent) +{ + strmOut << "\n"; + + GrPass * ppass = Pass(ipass); + GrSlotStream * psstrmIn = (ipass == 0) ? NULL : InputStream(ipass); + GrSlotStream * psstrmOut = OutputStream(ipass); + + int islot; + // Mark each slot with its index in the input and output streams. + for (islot = 0; ipass > 0 && islot < psstrmIn->ReadPos(); islot++) + psstrmIn->SlotAt(islot)->m_islotTmpIn = islot; + + for (islot = 0; islot < psstrmOut->WritePos(); islot++) + psstrmOut->SlotAt(islot)->m_islotTmpOut = islot; + + LogXmlTagOpen(strmOut, "Pass", nIndent, true); + LogXmlTagAttr(strmOut, "number", ipass); + + std::string strType; + if (dynamic_cast<GrGlyphGenPass *>(ppass)) + strType = "glyphGeneration"; + else if (dynamic_cast<GrBidiPass *>(ppass)) + strType = "bidi"; + else if (dynamic_cast<GrSubPass *>(ppass)) + { + if (ipass >= m_ipassJust1) + strType = "justification"; + else + strType = "substitution"; + } + else if (dynamic_cast<GrPosPass *>(ppass)) + strType = "positioning"; + else if (dynamic_cast<GrLineBreakPass *>(ppass)) + strType = "linebreak"; + LogXmlTagAttr(strmOut, "type", strType.c_str()); + + LogXmlTagPostAttrs(strmOut, true); + + if (!dynamic_cast<GrBidiPass *>(ppass) && !dynamic_cast<GrGlyphGenPass *>(ppass)) + { + LogXmlTagOpen(strmOut, "RulesMatched", nIndent+1, true); + LogXmlTagPostAttrs(strmOut, true); + ppass->LogXmlRules(strmOut, this, psstrmIn, nIndent+2); + LogXmlTagClose(strmOut, "RulesMatched", nIndent+1, true); + } + + bool fJustWidths = false; + if (ipass == m_ipassJust1 - 1 && ShouldLogJustification() + && m_engst.m_jmodi == kjmodiJustify) + { + fJustWidths = true; + } + + LogXmlTagOpen(strmOut, "Output", nIndent+1, true); + LogXmlTagPostAttrs(strmOut, true); + bool fPreJust = (!fJustWidths && ipass == m_ipassJust1 - 1 && ShouldLogJustification()); + bool fPostJust = (fJustWidths || ipass == m_ipassJust1 && ShouldLogJustification()); + ppass->LogXmlGlyphs(strmOut, this, psstrmOut, m_ipassJust1, fPreJust, fPostJust, cslotSkipped, nIndent+2); + LogXmlTagClose(strmOut, "Output", nIndent+1, true); + + LogXmlTagClose(strmOut, "Pass", nIndent, true); + +#ifdef XMLOMIT + + // If this was the pass just before the justification routines get run, output a + // special line that just shows the results, ie, the values of justify.width. + // TODO: adjust this when measure mode get functioning. + if (ipass == m_ipassJust1 - 1 && ShouldLogJustification() + && m_engst.m_jmodi == kjmodiJustify) + { + strmOut << "\nJUSTIFICATION\n\n"; + LogSlotHeader(strmOut, psstrmOut->WritePos(), SP_PER_SLOT, LEADING_SP); + LogSlotGlyphs(strmOut, psstrmOut); + LogAttributes(strmOut, ipass, true); + } + +#endif // XMLOMIT + +} + +/*---------------------------------------------------------------------------------------------- + Write the list of rules fired and failed for a given pass. +----------------------------------------------------------------------------------------------*/ +void GrPass::LogXmlRules(std::ostream & strmOut, GrTableManager * ptman, + GrSlotStream * psstrmIn, int nIndent) +{ + m_pzpst->LogXmlRules(strmOut, ptman, psstrmIn, nIndent); +} + +void PassState::LogXmlRules(std::ostream & strmOut, GrTableManager * ptman, + GrSlotStream * psstrmIn, int nIndent) +{ + if (m_crulrec == 0) + { + ptman->LogXmlComment(strmOut, "none", nIndent); + return; + } + + for (int irulrec = 0; irulrec < m_crulrec; irulrec++) + { + bool fSourceAvailable = false; + + ptman->LogXmlTagOpen(strmOut, "Rule", nIndent, fSourceAvailable); + + ptman->LogXmlTagAttr(strmOut, "slot", m_rgrulrec[irulrec].m_islot); + + if (m_rgrulrec[irulrec].m_irul == PassState::kHitMaxRuleLoop) + ptman->LogXmlTagAttr(strmOut, "hitMaxRuleLoop", "true"); + else if (m_rgrulrec[irulrec].m_irul == PassState::kHitMaxBackup) + ptman->LogXmlTagAttr(strmOut, "hitMaxBackup", "true"); + else + { + ptman->LogXmlTagAttr(strmOut, "debugNumber", m_rgrulrec[irulrec].m_irul); + ptman->LogXmlTagAttr(strmOut, "fired", (m_rgrulrec[irulrec].m_fFired) ? "true" : "false"); + } + + ptman->LogXmlTagPostAttrs(strmOut, fSourceAvailable); + + // TODO: output Source + + ptman->LogXmlTagClose(strmOut, "Rule", nIndent, fSourceAvailable); + } +} + +void GrPass::LogXmlGlyphs(std::ostream & strmOut, GrTableManager * ptman, GrSlotStream * psstrmOut, + int ipassJust1, bool fPreJust, bool fPostJust, int cslotSkipped, int nIndent) +{ + GrBidiPass * ppassBidi = dynamic_cast<GrBidiPass *>(this); + GrBidiPass * ppassBidiNext = (m_ipass + 1 >= ptman->NumberOfPasses()) ? + NULL : + dynamic_cast<GrBidiPass *>(ptman->Pass(m_ipass + 1)); + m_pzpst->LogXmlGlyphs(strmOut, ptman, psstrmOut, ipassJust1, fPreJust, fPostJust, + (ppassBidi != NULL), (ppassBidiNext != NULL), cslotSkipped, nIndent); +} + +void PassState::LogXmlGlyphs(std::ostream & strmOut, GrTableManager * ptman, GrSlotStream * psstrmOut, + int ipassJust1, bool fPreJust, bool fPostJust, bool fBidi, bool fBidiNext, int cslotSkipped, + int nIndent) +{ + ptman->LogXmlTagOpen(strmOut, "Output", nIndent, true); + ptman->LogXmlTagPostAttrs(strmOut, true); + + for (int islot = 0; islot < psstrmOut->WritePos() + 1; islot++) // +1 allows us to handle final deletion + { + if (islot > MAX_SLOTS) + break; + + for (int islotDel = 0; islotDel < m_rgcslotDeletions[islot]; islotDel++) + { + ptman->LogXmlTagOpen(strmOut, "Glyph", nIndent+1, false); + ptman->LogXmlTagAttr(strmOut, "slot", "deleted"); + ptman->LogXmlTagPostAttrs(strmOut, false); + ptman->LogXmlTagClose(strmOut, "Glyph", nIndent+1, false); + } + if (islot >= psstrmOut->WritePos()) + break; + + GrSlotState * pslot = psstrmOut->SlotAt(islot); + + bool fMod = (pslot->PassModified() >= m_ipass && m_ipass > 0); + if (fBidi || fBidiNext) + fMod = true; + + ptman->LogXmlTagOpen(strmOut, "Glyph", nIndent+1, fMod); + + ptman->LogXmlTagAttr(strmOut, "slot", islot); + if (pslot->GlyphID() == ptman->LBGlyphID()) + ptman->LogXmlTagAttr(strmOut, "gid", "linebreak"); + else + ptman->LogXmlTagAttr(strmOut, "gid", pslot->GlyphID()); + if (pslot->GlyphID() != pslot->ActualGlyphForOutput(ptman)) + ptman->LogXmlTagAttr(strmOut, "actual", pslot->ActualGlyphForOutput(ptman)); + if (m_rgfInsertion[islot]) + ptman->LogXmlTagAttr(strmOut, "inserted", "true"); + if (islot < cslotSkipped) + ptman->LogXmlTagAttr(strmOut, "nextPassSkips", "true"); + + ptman->LogXmlTagPostAttrs(strmOut, fMod); + + if (fMod) + { + pslot->LogXmlAttributes(strmOut, ptman, psstrmOut, m_ipass, islot, + fPreJust, fPostJust, fBidi, fBidiNext, nIndent+2); + } + + ptman->LogXmlTagClose(strmOut, "Glyph", nIndent+1, fMod); + } + + ptman->LogXmlTagClose(strmOut, "Output", nIndent, true); +} + +/*---------------------------------------------------------------------------------------------- + Write out the attributes that have changes. +----------------------------------------------------------------------------------------------*/ +void GrSlotState::LogXmlAttributes(std::ostream & strmOut, GrTableManager * ptman, + GrSlotStream * psstrmOut, int ipass, + int islot, bool fPreJust, bool fPostJust, bool fBidi, bool fBidiNext, int nIndent) +{ + // To handle reprocessing, in which case there may be a chain of slots modified + // in the same pass: + GrSlotState * pslotPrev = PrevState(); + while (pslotPrev && pslotPrev->PassModified() == PassModified()) + pslotPrev = pslotPrev->m_pslotPrevState; + + bool * prgfMods = new bool[kslatMax + ptman->NumUserDefn() - 1]; + memset(prgfMods, 0, (kslatMax + ptman->NumUserDefn() - 1) * sizeof(bool)); + int ccomp; + int cassoc; + SlotAttrsModified(prgfMods, fPreJust, &ccomp, &cassoc); // just for this one slot + + if (fPreJust) + prgfMods[kslatJWidth] = false; + else if (fPostJust) + prgfMods[kslatJWidth] = true; + + //if (fJustWidths) + //{} + + bool fLogAssocs = false; + + for (int slat = 0; slat < kslatMax + ptman->NumUserDefn() - 1; slat++) + { + if (!prgfMods[slat] && (slat != kslatDir || (!fBidi && !fBidiNext))) + continue; + + if (slat == kslatPosX) + continue; + if (slat == kslatPosY) + continue; + + std::string strAttrName; + switch (slat) + { + case kslatAdvX: strAttrName = "advance.x"; break; + case kslatAdvY: strAttrName = "advance.y"; break; + case kslatAttTo: strAttrName = "att.to"; break; + case kslatAttAtX: strAttrName = "att.at.x"; break; + case kslatAttAtY: strAttrName = "att.at.y"; break; + case kslatAttAtGpt: strAttrName = "att.at.gpt"; break; + case kslatAttAtXoff: strAttrName = "att.at.xoff"; break; + case kslatAttAtYoff: strAttrName = "att.at.yoff"; break; + case kslatAttWithX: strAttrName = "att.with.x"; break; + case kslatAttWithY: strAttrName = "att.with.y"; break; + case kslatAttWithGpt: strAttrName = "att.with.gpt"; break; + case kslatAttWithXoff: strAttrName = "att.with.xoff"; break; + case kslatAttWithYoff: strAttrName = "att.with.yoff"; break; + case kslatAttLevel: strAttrName = "att.level"; break; + case kslatBreak: strAttrName = "breakweight"; break; + case kslatCompRef: strAttrName = "component"; break; // << iIndex + 1 - 1-based + case kslatDir: strAttrName = "dir"; break; + case kslatInsert: strAttrName = "insert"; break; + case kslatMeasureSol: strAttrName = "measure.sol"; break; + case kslatMeasureEol: strAttrName = "measure.eol"; break; + case kslatJStretch: strAttrName = "just.stretch"; break; + case kslatJShrink: strAttrName = "just.shrink"; break; + case kslatJStep: strAttrName = "just.step"; break; + case kslatJWeight: strAttrName = "just.weight"; break; + case kslatJWidth: strAttrName = "just.width"; break; + case kslatPosX: + case kslatPosY: + Assert(false); + break; + case kslatShiftX: strAttrName = "shift.x"; break; + case kslatShiftY: strAttrName = "shift.y"; break; + default: + if (kslatUserDefn <= slat && + slat < kslatUserDefn + ptman->NumUserDefn()) + { + strAttrName.assign("user"); + char rgch[20]; + itoa(slat - kslatUserDefn + 1, rgch, 10); // 1-based + strAttrName.append(rgch); + } + else + { + // Invalid attribute: + Warn("bad slot attribute"); + break; + } + } + + fLogAssocs = (fLogAssocs || prgfMods[slat]); + + if (slat == kslatCompRef) + { + for (int icomp = 0; icomp < ccomp; icomp++) + { + ptman->LogXmlTagOpen(strmOut, "Attribute", nIndent, false); + ptman->LogXmlTagAttr(strmOut, "name", strAttrName.c_str()); + ptman->LogXmlTagAttr(strmOut, "index", icomp+1); + int nValue = GetSlotAttrValue(strmOut, ptman, ipass, slat, icomp, fPreJust, fPostJust); + ptman->LogXmlTagAttr(strmOut, "newValue", nValue); + ptman->LogXmlTagPostAttrs(strmOut, false); + ptman->LogXmlTagClose(strmOut, "Attribute", nIndent, false); + } + } + else + { + std::string strValue = "newValue"; + if ((!prgfMods[slat] && fBidiNext) || fBidi) + strValue = "value"; + + ptman->LogXmlTagOpen(strmOut, "Attribute", nIndent, false); + ptman->LogXmlTagAttr(strmOut, "name", strAttrName.c_str()); + int nValue = GetSlotAttrValue(strmOut, ptman, ipass, slat, 0, fPreJust, fPostJust); + switch (slat) + { + case kslatDir: ptman->LogXmlDirCode(strmOut, strValue.c_str(), nValue);break; + case kslatBreak: ptman->LogXmlBreakWeight(strmOut, "newValue", nValue); break; + default: ptman->LogXmlTagAttr(strmOut, "newValue", nValue); break; + } + ptman->LogXmlTagPostAttrs(strmOut, false); + ptman->LogXmlTagClose(strmOut, "Attribute", nIndent, false); + } + } + + if (fBidi) + { + // Output final directionality level + ptman->LogXmlTagOpen(strmOut, "Attribute", nIndent, false); + ptman->LogXmlTagAttr(strmOut, "name", "directionLevel"); + ptman->LogXmlTagAttr(strmOut, "value", DirLevel()); + ptman->LogXmlTagPostAttrs(strmOut, false); + ptman->LogXmlTagClose(strmOut, "Attribute", nIndent, false); + } + + if (m_vpslotAssoc.size() > 1) + fLogAssocs = true; // multiple associations + else if (m_vpslotAssoc.size() == 1) + { + // association change from previous stream + GrSlotState * pslotAssoc = AssocSlot(0); + if (pslotAssoc == NULL || pslotAssoc->m_islotTmpIn != islot) + fLogAssocs = true; + } + if (fLogAssocs) + { + std::string strAssocs; + char rgch[20]; + for (size_t iassoc = 0; iassoc < m_vpslotAssoc.size(); iassoc++) + { + GrSlotState * pslotAssoc = AssocSlot(iassoc); + if (pslotAssoc) + { + int n = pslotAssoc->m_islotTmpIn; + memset(rgch,0,20); + itoa(n,rgch,10); + if (iassoc > 0) + strAssocs.append(" "); + strAssocs.append(rgch); + } + } + if (strAssocs.length() == 0) + strAssocs.assign("??"); + ptman->LogXmlTagOpen(strmOut, "Associations", nIndent, false); + ptman->LogXmlTagAttr(strmOut, "slots", strAssocs.c_str()); + //ptman->LogXmlTagPostAttrs(strmOut, false); + ptman->LogXmlTagClose(strmOut, "Associations", nIndent, false); + } + + delete prgfMods; +} + +#if XMLOMIT +/*---------------------------------------------------------------------------------------------- + Write out the final positions. +----------------------------------------------------------------------------------------------*/ +void GrTableManager::LogFinalPositions(std::ostream & strmOut) +{ + GrSlotStream * psstrm = OutputStream(m_cpass - 1); + + strmOut << "x position "; + for (int islot = 0; islot < psstrm->WritePos(); islot++) + { + GrSlotState * pslot = psstrm->SlotAt(islot); + if (pslot->IsLineBreak(LBGlyphID())) + { + strmOut << " "; + continue; + } + LogInTable(strmOut, pslot->XPosition()); + } + strmOut << "\n"; + + strmOut << "y position "; + for (int islot = 0; islot < psstrm->WritePos(); islot++) + { + GrSlotState * pslot = psstrm->SlotAt(islot); + if (pslot->IsLineBreak(LBGlyphID())) + { + strmOut << " "; + continue; + } + LogInTable(strmOut, pslot->YPosition()); + } + strmOut << "\n"; +} + +#endif // XMLOMIT + +/*---------------------------------------------------------------------------------------------- + Log the value of the slot attribute for the given slot. Assume it has changed. +----------------------------------------------------------------------------------------------*/ +int GrSlotState::GetSlotAttrValue(std::ostream & strmOut, GrTableManager * ptman, + int ipass, int slat, int iIndex, bool fPreJust, bool fPostJust) +{ + switch (slat) + { + case kslatAdvX: + return int(m_mAdvanceX); + case kslatAdvY: + return int(m_mAdvanceY); + + case kslatAttTo: + return m_srAttachTo; + + case kslatAttAtX: // always do these in pairs + return m_mAttachAtX; + case kslatAttAtY: + return m_mAttachAtY; + case kslatAttAtGpt: + return m_nAttachAtGpoint; + + case kslatAttAtXoff: // always do these in pairs + return m_mAttachAtXOffset; + case kslatAttAtYoff: + return m_mAttachAtYOffset; + + case kslatAttWithX: // always do these in pairs + return m_mAttachWithX; + case kslatAttWithY: + return m_mAttachWithY; + + case kslatAttWithGpt: + return m_nAttachWithGpoint; + + case kslatAttWithXoff: // always do these in pairs + return m_mAttachWithXOffset; + case kslatAttWithYoff: + return m_mAttachWithYOffset; + + case kslatAttLevel: + return m_nAttachLevel; + + case kslatBreak: + return m_lb; + + case kslatDir: + return m_dirc; + + case kslatInsert: + return m_fInsertBefore; + + case kslatShiftX: + return m_mShiftX; + case kslatShiftY: + return m_mShiftY; + case kslatMeasureSol: + return m_mMeasureSol; + case kslatMeasureEol: + return m_mMeasureEol; + case kslatJStretch: + return m_mJStretch0; + case kslatJShrink: + return m_mJShrink0; + case kslatJStep: + return m_mJStep0; + case kslatJWeight: + return m_nJWeight0; + case kslatJWidth: + return m_mJWidth0; + + case kslatCompRef: + { + GrSlotState * pslotComp = reinterpret_cast<GrSlotState *>(CompRef(iIndex)); + return pslotComp->m_islotTmpIn; + } + + default: + if (kslatUserDefn <= slat && slat <= kslatUserDefn + m_cnUserDefn) + { + int iTmp = slat - kslatUserDefn; + return UserDefn(iTmp); + } + else + gAssert(false); + } + + return 0; +} + +#endif // TRACING + + +/*---------------------------------------------------------------------------------------------- + Write out the final underlying-to-surface associations. +----------------------------------------------------------------------------------------------*/ +void Segment::LogXmlUnderlyingToSurface(std::ostream & strmOut, GrTableManager * ptman, + GrCharStream * pchstrm, int nIndent) +{ +#ifdef TRACING + + ptman->LogXmlTagOpen(strmOut, "UnderlyingToSurface", nIndent, true); + ptman->LogXmlTagPostAttrs(strmOut, true); + + ptman->LogXmlUnderlyingAux(strmOut, pchstrm, -m_ichwAssocsMin, (m_ichwAssocsLim - m_ichwAssocsMin), + nIndent+1, + true, // text + false, // features + false, // color + true, // string offset + true, // ligature components + true // glyph associations + ); + + ptman->LogXmlTagClose(strmOut, "UnderlyingToSurface", nIndent, true); + + +#ifdef XMLOMIT + ptman->LogXmlTagOpen(strmOut, "UnderlyingToSurface", nIndent, true); + + size_t cassocs = 0; + int fLigs = false; + int ichw; + for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) + { + if (m_prgpvisloutAssocs[ichw]) + cassocs = max(cassocs, m_prgpvisloutAssocs[ichw]->size()); + if (m_prgisloutLigature[ichw] != kNegInfinity) + fLigs = true; + } + + ptman->LogUnderlyingHeader(strmOut, pchstrm->Min(), (pchstrm->Min() + m_ichwAssocsLim), + -m_ichwAssocsMin, NULL); + + int rgnChars[MAX_SLOTS]; + bool rgfNewRun[MAX_SLOTS]; + std::fill_n(rgfNewRun, MAX_SLOTS, false); + GrFeatureValues rgfval[MAX_SLOTS]; + int cchwMaxRawChars; + + int cchw = pchstrm->GetLogData(ptman, rgnChars, rgfNewRun, rgfval, + -m_ichwAssocsMin, &cchwMaxRawChars); + cchw = min(cchw, MAX_SLOTS); + + utf16 rgchwChars2[MAX_SLOTS]; + utf16 rgchwChars3[MAX_SLOTS]; + utf16 rgchwChars4[MAX_SLOTS]; + utf16 rgchwChars5[MAX_SLOTS]; + utf16 rgchwChars6[MAX_SLOTS]; + int rgcchwRaw[MAX_SLOTS]; + if (cchwMaxRawChars > 1) + { + cchwMaxRawChars = min(cchwMaxRawChars, 6); + pchstrm->GetLogDataRaw(ptman, cchw, -m_ichwAssocsMin, cchwMaxRawChars, + rgnChars, rgchwChars2, rgchwChars3, rgchwChars4, rgchwChars5, rgchwChars6, + rgcchwRaw); + } + else + { + for (ichw = 0 ; ichw <(m_ichwAssocsLim - m_ichwAssocsMin); ichw++) + { + rgcchwRaw[ichw] = 1; + rgchwChars2[ichw] = 0; + rgchwChars3[ichw] = 0; + rgchwChars4[ichw] = 0; + rgchwChars5[ichw] = 0; + rgchwChars6[ichw] = 0; + } + } + + // Text + strmOut << "Text: "; // 15 spaces + int inUtf32 = 0; + for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) + { + utf16 chw, chwNext; + switch (rgcchwRaw[ichw]) + { + default: + case 1: chw = utf16(rgnChars[inUtf32]); chwNext = rgchwChars2[inUtf32]; break; + case 2: chw = rgchwChars2[inUtf32]; chwNext = rgchwChars3[inUtf32]; break; + case 3: chw = rgchwChars3[inUtf32]; chwNext = rgchwChars4[inUtf32]; break; + case 4: chw = rgchwChars4[inUtf32]; chwNext = rgchwChars5[inUtf32]; break; + case 5: chw = rgchwChars5[inUtf32]; chwNext = rgchwChars6[inUtf32]; break; + case 6: chw = rgchwChars6[inUtf32]; chwNext = 0; break; + } + if (rgcchwRaw[ichw] == 1 && chwNext == 0 && chw < 0x0100) // ANSI + strmOut << (char)chw << " "; // 6 spaces + else + strmOut << " "; // 7 spaces + if (chwNext == 0) + inUtf32++; + } + strmOut << "\n"; + + // Unicode + strmOut << "Unicode: "; + inUtf32 = 0; + for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) + { + utf16 chw, chwNext; + switch (rgcchwRaw[ichw]) + { + default: + case 1: chw = utf16(rgnChars[inUtf32]); chwNext = rgchwChars2[inUtf32]; break; + case 2: chw = rgchwChars2[inUtf32]; chwNext = rgchwChars3[inUtf32]; break; + case 3: chw = rgchwChars3[inUtf32]; chwNext = rgchwChars4[inUtf32]; break; + case 4: chw = rgchwChars4[inUtf32]; chwNext = rgchwChars5[inUtf32]; break; + case 5: chw = rgchwChars5[inUtf32]; chwNext = rgchwChars6[inUtf32]; break; + case 6: chw = rgchwChars6[inUtf32]; chwNext = 0; break; + } + ptman->LogHexInTable(strmOut, chw, chwNext != 0); + if (chwNext == 0) + inUtf32++; + } + strmOut << "\n"; + + strmOut << "before "; + for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) + { + if (rgcchwRaw[ichw] > 1) + // continuation of Unicode codepoint + strmOut << " "; + else if (m_prgisloutBefore[ichw] == kNegInfinity) + strmOut << "<-- "; + else if (m_prgisloutBefore[ichw] == kPosInfinity) + strmOut << "--> "; + else + ptman->LogInTable(strmOut, m_prgisloutBefore[ichw]); + } + strmOut <<"\n"; + + for (int ix = 1; ix < signed(cassocs) - 1; ix++) //(cassocs > 2) + { + if (ix == 1) + strmOut << "other "; + else + strmOut << " "; + for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) + { + std::vector<int> * pvislout = m_prgpvisloutAssocs[ichw]; + if (pvislout == NULL) + strmOut << " "; + else if (signed(pvislout->size()) <= ix) + strmOut << " "; + else if ((*pvislout)[ix] != m_prgisloutAfter[ichw]) + ptman->LogInTable(strmOut, (*pvislout)[ix]); + else + strmOut << " "; + } + strmOut << "\n"; + } + + strmOut << "after "; + for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) + { + if (rgcchwRaw[ichw] > 1) + // continuation of Unicode codepoint + strmOut << " "; + else if (m_prgisloutAfter[ichw] == kNegInfinity) + strmOut << "<-- "; + else if (m_prgisloutAfter[ichw] == kPosInfinity) + strmOut << "--> "; + else + ptman->LogInTable(strmOut, m_prgisloutAfter[ichw]); + } + strmOut <<"\n"; + + if (fLigs) + { + strmOut << "ligature "; + for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) + { + if (rgcchwRaw[ichw] > 1) + // continuation of Unicode codepoint + strmOut << " "; + else if (m_prgisloutLigature[ichw] != kNegInfinity) + ptman->LogInTable(strmOut, m_prgisloutLigature[ichw]); + else + strmOut << " "; + } + strmOut << "\n"; + + strmOut << "component "; + for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++) + { + if (rgcchwRaw[ichw] > 1) + // continuation of Unicode codepoint + strmOut << " "; + else if (m_prgisloutLigature[ichw] != kNegInfinity) + ptman->LogInTable(strmOut, m_prgiComponent[ichw] + 1); // 1-based + else + strmOut << " "; + } + strmOut << "\n"; + } + + strmOut << "\n"; +#endif // XMLOMIT +#endif // TRACING + +} + +#ifdef XMLOMIT + +/*---------------------------------------------------------------------------------------------- + Write out the final surface-to-underlying associations. +----------------------------------------------------------------------------------------------*/ +void Segment::LogSurfaceToUnderlying(GrTableManager * ptman, std::ostream & strmOut) +{ +#ifdef TRACING + strmOut << "\nSURFACE TO UNDERLYING MAPPINGS\n\n"; + + ptman->LogSlotHeader(strmOut, m_cslout, SP_PER_SLOT, LEADING_SP); + + int ccomp = 0; + + strmOut << "Glyph IDs: "; + int islout; + for (islout = 0; islout < m_cslout; islout++) + { + GrSlotOutput * psloutTmp = m_prgslout + islout; + if (psloutTmp->SpecialSlotFlag() == kspslLbInitial || + psloutTmp->SpecialSlotFlag() == kspslLbFinal) + { + strmOut << "# "; + } + else + { + ptman->LogHexInTable(strmOut, psloutTmp->GlyphID()); + ccomp = max(ccomp, psloutTmp->NumberOfComponents()); + } + } + strmOut << "\n"; + + bool fAnyPseudos = false; + for (islout = 0; islout < m_cslout; islout++) + { + GrSlotOutput * psloutTmp = m_prgslout + islout; + if (psloutTmp->GlyphID() != psloutTmp->ActualGlyphForOutput(ptman)) + { + fAnyPseudos = true; + break; + } + } + if (fAnyPseudos) + { + strmOut << "Actual glyphs: "; + for (int islout = 0; islout < m_cslout; islout++) + { + GrSlotOutput * psloutTmp = m_prgslout + islout; + if (psloutTmp->GlyphID() != psloutTmp->ActualGlyphForOutput(ptman)) + ptman->LogHexInTable(strmOut, psloutTmp->ActualGlyphForOutput(ptman)); + else + strmOut << " "; + } + strmOut << "\n"; + } + + strmOut << "before "; + for (islout = 0; islout < m_cslout; islout++) + { + GrSlotOutput * psloutTmp = m_prgslout + islout; + if (psloutTmp->SpecialSlotFlag() == kspslLbInitial || + psloutTmp->SpecialSlotFlag() == kspslLbFinal) + { + strmOut << " "; + } + else + ptman->LogInTable(strmOut, psloutTmp->BeforeAssoc()); + } + strmOut << "\n"; + + strmOut << "after "; + for (islout = 0; islout < m_cslout; islout++) + { + GrSlotOutput * psloutTmp = m_prgslout + islout; + if (psloutTmp->SpecialSlotFlag() == kspslLbInitial || + psloutTmp->SpecialSlotFlag() == kspslLbFinal) + { + strmOut << " "; + } + else + ptman->LogInTable(strmOut, psloutTmp->AfterAssoc()); + } + strmOut << "\n"; + + for (int icomp = 0; icomp < ccomp; icomp++) + { + strmOut << "component " << icomp + 1 // 1=based + << " "; + for (islout = 0; islout < m_cslout; islout++) + { + GrSlotOutput * psloutTmp = m_prgslout + islout; + if (psloutTmp->SpecialSlotFlag() == kspslLbInitial || + psloutTmp->SpecialSlotFlag() == kspslLbFinal) + { + strmOut << " "; + } + else if (icomp < psloutTmp->NumberOfComponents()) + ptman->LogInTable(strmOut, psloutTmp->UnderlyingComponent(icomp)); + else + strmOut << " "; + } + strmOut << "\n"; + } +#endif // TRACING +} + +#ifdef TRACING +/*---------------------------------------------------------------------------------------------- + Log the value of the association, if the slot changed. +----------------------------------------------------------------------------------------------*/ +void GrSlotState::LogAssociation(GrTableManager * ptman, + std::ostream & strmOut, int ipass, int iassoc, bool fBoth, bool fAfter) +{ + if (m_ipassModified != ipass) + { + strmOut << " "; + return; + } + + if (fBoth) + { + GrSlotState * pslotBefore = (m_vpslotAssoc.size()) ? m_vpslotAssoc[0] : NULL; + GrSlotState * pslotAfter = (m_vpslotAssoc.size()) ? m_vpslotAssoc.back() : NULL; + // handle possible reprocessing + while (pslotBefore && pslotBefore->PassModified() == m_ipassModified) + pslotBefore = pslotBefore->m_pslotPrevState; + while (pslotAfter && pslotAfter->PassModified() == m_ipassModified) + pslotAfter = pslotAfter->m_pslotPrevState; + + int nBefore, nAfter; + + + int csp = 4; + if (pslotBefore) + { + nBefore = pslotBefore->m_islotTmpIn; + strmOut << nBefore; + if (nBefore > 99) csp--; + if (nBefore > 9) csp--; + } + else + { + strmOut << "??"; + csp--; + } + if (pslotAfter) + { + nAfter = pslotAfter->m_islotTmpIn; + strmOut << "/" << nAfter; + if (nAfter > 99) csp--; + if (nAfter > 9) csp--; + } + else + { + if (pslotBefore) + { + strmOut << "/" << "??"; + csp--; + } + else + csp = 5; + } + + for (int isp = 0; isp < csp; isp++) + strmOut << " "; + } + + else if (fAfter) + { + Assert(m_vpslotAssoc.size()); + GrSlotState * pslotAfter = m_vpslotAssoc.back(); + // handle possible reprocessing + while (pslotAfter && pslotAfter->PassModified() == m_ipassModified) + pslotAfter = pslotAfter->m_pslotPrevState; + + if (pslotAfter) + { + int nAfter = pslotAfter->m_islotTmpIn; + ptman->LogInTable(strmOut, nAfter); + } + else + strmOut << "?? "; + } + else if (iassoc < signed(m_vpslotAssoc.size())) + { + GrSlotState * pslot = m_vpslotAssoc[iassoc]; + // handle possible reprocessing + while (pslot && pslot->PassModified() == m_ipassModified) + pslot = pslot->m_pslotPrevState; + + if (pslot) + { + int n = pslot->m_islotTmpIn; + ptman->LogInTable(strmOut, n); + } + else + strmOut << "?? "; + } + else + strmOut << " "; +} + + +/*---------------------------------------------------------------------------------------------- + Write a directionality code to the table. +----------------------------------------------------------------------------------------------*/ +void GrTableManager::LogDirCodeInTable(std::ostream & strmOut, int dirc) +{ + switch (dirc) + { + case kdircUnknown: strmOut << "??? "; break; + case kdircNeutral: strmOut << "ON "; break; + case kdircL: strmOut << "L "; break; + case kdircR: strmOut << "R "; break; + case kdircRArab: strmOut << "AR "; break; + case kdircEuroNum: strmOut << "EN "; break; + case kdircEuroSep: strmOut << "ES "; break; + case kdircEuroTerm: strmOut << "ET "; break; + case kdircArabNum: strmOut << "AN "; break; + case kdircComSep: strmOut << "CS "; break; + case kdircWhiteSpace: strmOut << "WS "; break; + case kdircBndNeutral: strmOut << "BN "; break; + case kdircNSM: strmOut << "NSM "; break; + case kdircLRO: strmOut << "LRO "; break; + case kdircRLO: strmOut << "RLO "; break; + case kdircLRE: strmOut << "LRE "; break; + case kdircRLE: strmOut << "RLE "; break; + case kdircPDF: strmOut << "PDF "; break; + case kdircPdfL: strmOut << "PDF-L "; break; + case kdircPdfR: strmOut << "PDF-R "; break; + case kdircLlb: strmOut << "L "; break; + case kdircRlb: strmOut << "R "; break; + default: LogInTable(strmOut, dirc); break; + } +} + +/*---------------------------------------------------------------------------------------------- + Write a breakweight code to the table. +----------------------------------------------------------------------------------------------*/ +void GrTableManager::LogBreakWeightInTable(std::ostream & strmOut, int lb) +{ + if (lb < 0) + { + lb = lb * -1; + switch (lb) + { + case klbWsBreak: strmOut << "-ws "; break; + case klbWordBreak: strmOut << "-word "; break; + case klbHyphenBreak: strmOut << "-intra "; break; + case klbLetterBreak: strmOut << "-lettr "; break; + case klbClipBreak: strmOut << "-clip "; break; + default: LogInTable(strmOut, lb); break; + } + } + else + { + switch (lb) + { + case klbNoBreak: strmOut << "none "; break; + case klbWsBreak: strmOut << "ws "; break; + case klbWordBreak: strmOut << "word "; break; + case klbHyphenBreak: strmOut << "intra "; break; + case klbLetterBreak: strmOut << "letter "; break; + case klbClipBreak: strmOut << "clip "; break; + default: LogInTable(strmOut, lb); break; + } + } +} + +#endif // TRACING + +#endif // XMLOMIT + +#ifdef TRACING +/*---------------------------------------------------------------------------------------------- + Write an XML tag, leaving it open to possibly add attributes. +----------------------------------------------------------------------------------------------*/ +void GrTableManager::LogXmlTagOpen(std::ostream & strmOut, std::string strTag, size_t nIndent, + bool fContent) +{ + for (size_t i = 0; i < nIndent; i++) + strmOut << " "; + + strmOut << "<" << strTag; +} + +/*---------------------------------------------------------------------------------------------- + Write the termination of the opening XML tag. +----------------------------------------------------------------------------------------------*/ +void GrTableManager::LogXmlTagPostAttrs(std::ostream & strmOut, + bool fContent) +{ + if (fContent) + strmOut << ">\n"; +} + +/*---------------------------------------------------------------------------------------------- + Write the closing form of the XML tag. +----------------------------------------------------------------------------------------------*/ +void GrTableManager::LogXmlTagClose(std::ostream & strmOut, std::string strTag, size_t nIndent, + bool fContent) +{ + if (fContent) + { + for (size_t i = 0; i < nIndent; i++) + strmOut << " "; + strmOut << "</" << strTag << ">\n"; + } + else + { + strmOut << " />\n"; + } +} + +/*---------------------------------------------------------------------------------------------- + Write an attribute/value pair inside of a tag. +----------------------------------------------------------------------------------------------*/ +void GrTableManager::LogXmlTagAttr(std::ostream & strmOut, std::string strAttr, int nValue, + size_t nIndent) +{ + char chBuf[20]; + itoa(nValue, chBuf, 10); + LogXmlTagAttr(strmOut, strAttr, chBuf, nIndent); +} + +void GrTableManager::LogXmlTagAttr(std::ostream & strmOut, std::string strAttr, const char * szValue, + size_t nIndent) +{ + if (nIndent > 0) + { + strmOut << "\n"; + for (size_t i = 0; i < nIndent + 2; i++) + strmOut << " "; + } + else + strmOut << " "; + + strmOut << strAttr << "=\"" << szValue << "\""; +} + +void GrTableManager::LogXmlTagAttrHex(std::ostream & strmOut, std::string strAttr, int nValue, + size_t nIndent) +{ + char chBuf[20]; + chBuf[0] = chBuf[1] = chBuf[2] = '0'; + if (nValue < 0x10) + itoa(nValue, chBuf+3, 16); // prepend 3 zeros + else if (nValue < 0x100) + itoa(nValue, chBuf+2, 16); // prepend 2 zeros + else if (nValue < 0x1000) + itoa(nValue, chBuf+1, 16); // prepend 1 zero + else + itoa(nValue, chBuf, 16); + LogXmlTagAttr(strmOut, strAttr, chBuf, nIndent); +} + +/*---------------------------------------------------------------------------------------------- + Concatenate the hex form of the given numbers into a string. +----------------------------------------------------------------------------------------------*/ +std::string GrTableManager::HexString(std::vector<int> vn) +{ + std::string strRet; + for (size_t in = 0; in < vn.size(); in++) + { + char rgch[20]; + itoa(vn[in],rgch,16); + strRet.append(rgch); + if (in < vn.size() - 1) + strRet.append(" "); + } + return strRet; +} + +std::string GrTableManager::HexString(int n1, int n2, int n3, int n4, int n5, int n6) +{ + std::vector<int> vn; + if (n1 > 0) + { + vn.push_back(n1); + if (n2 > 0) + { + vn.push_back(n2); + if (n3 > 0) + { + vn.push_back(n3); + if (n4 > 0) + { + vn.push_back(n4); + if (n5 > 0) + { + vn.push_back(n5); + if (n6 > 0) + vn.push_back(n6); + } + } + } + } + } + return HexString(vn); +} + +/*---------------------------------------------------------------------------------------------- + Write an attribute/value pair inside of a tag. +----------------------------------------------------------------------------------------------*/ +void GrTableManager::LogXmlTagColor(std::ostream & strmOut, std::string strAttr, int clrValue, + bool fBack, size_t nIndent) +{ + // Ignore black foreground and white background. + if (!fBack && clrValue == kclrBlack) + return; + if (fBack && (clrValue == kclrWhite || clrValue == kclrTransparent)) + return; + + std::string strValue; + char rgch[20]; + switch (clrValue) + { + case kclrBlack: strValue = "black"; break; + case kclrWhite: strValue = "white"; break; + case kclrRed: strValue = "red"; break; + case kclrGreen: strValue = "green"; break; + case kclrBlue: strValue = "blue"; break; + case 0x00ffff: strValue = "yellow"; break; + case 0xff00ff: strValue = "magenta"; break; + case 0xffff00: strValue = "cyan"; break; + default: + rgch[0] = '#'; + itoa(clrValue, rgch+1, 16); + strValue.assign(rgch); + break; + } + + LogXmlTagAttr(strmOut, strAttr, strValue.c_str(), nIndent); +} + +/*---------------------------------------------------------------------------------------------- + Write a directionality code to the table. +----------------------------------------------------------------------------------------------*/ +void GrTableManager::LogXmlDirCode(std::ostream & strmOut, std::string strAttr, int dircValue, + size_t nIndent) +{ + std::string strValue; + char rgch[20]; + switch (dircValue) + { + case kdircUnknown: strValue = "unknown"; break; + case kdircNeutral: strValue = "ON"; break; + case kdircL: strValue = "L"; break; + case kdircR: strValue = "R"; break; + case kdircRArab: strValue = "AR"; break; + case kdircEuroNum: strValue = "EN"; break; + case kdircEuroSep: strValue = "ES"; break; + case kdircEuroTerm: strValue = "ET"; break; + case kdircArabNum: strValue = "AN"; break; + case kdircComSep: strValue = "CS"; break; + case kdircWhiteSpace: strValue = "WS"; break; + case kdircBndNeutral: strValue = "BN"; break; + case kdircNSM: strValue = "NSM"; break; + case kdircLRO: strValue = "LRO"; break; + case kdircRLO: strValue = "RLO"; break; + case kdircLRE: strValue = "LRE"; break; + case kdircRLE: strValue = "RLE"; break; + case kdircPDF: strValue = "PDF"; break; + case kdircPdfL: strValue = "PDF-L"; break; + case kdircPdfR: strValue = "PDF-R"; break; + case kdircLlb: strValue = "L"; break; + case kdircRlb: strValue = "R"; break; + default: + itoa(dircValue, rgch, 10); + strValue.assign(rgch); + break; + } + LogXmlTagAttr(strmOut, strAttr, strValue.c_str(), nIndent); +} + +/*---------------------------------------------------------------------------------------------- + Write a breakweight code to the table. +----------------------------------------------------------------------------------------------*/ +void GrTableManager::LogXmlBreakWeight(std::ostream & strmOut, std::string strAttr, int lbValue, + size_t nIndent) +{ + std::string strValue; + char rgch[20]; + if (lbValue < 0) + { + lbValue = lbValue * -1; + switch (lbValue) + { + case klbWsBreak: strValue = "-ws"; break; + case klbWordBreak: strValue = "-word"; break; + case klbHyphenBreak: strValue = "-intra"; break; + case klbLetterBreak: strValue = "-letter"; break; + case klbClipBreak: strValue = "-clip"; break; + default: + itoa(lbValue * -1, rgch, 10); + strValue.assign(rgch); + break; + } + } + else + { + switch (lbValue) + { + case klbNoBreak: strValue = "none"; break; + case klbWsBreak: strValue = "ws"; break; + case klbWordBreak: strValue = "word"; break; + case klbHyphenBreak: strValue = "intra"; break; + case klbLetterBreak: strValue = "letter"; break; + case klbClipBreak: strValue = "clip"; break; + default: + itoa(lbValue, rgch, 10); + strValue.assign(rgch); + break; + } + } + LogXmlTagAttr(strmOut, strAttr, strValue.c_str(), nIndent); +} + +/*---------------------------------------------------------------------------------------------- + Add a comment to the log file. +----------------------------------------------------------------------------------------------*/ +void GrTableManager::LogXmlComment(std::ostream & strmOut, std::string strComment, + size_t nIndent) +{ + for (size_t i = 0; i < nIndent; i++) + strmOut << " "; + + strmOut << "<!-- " << strComment << " -->\n"; +} + + +#endif // TRACING + +} // namespace gr |