diff options
Diffstat (limited to 'Build/source/libs/graphite/include/graphite/Segment.h')
-rw-r--r-- | Build/source/libs/graphite/include/graphite/Segment.h | 627 |
1 files changed, 627 insertions, 0 deletions
diff --git a/Build/source/libs/graphite/include/graphite/Segment.h b/Build/source/libs/graphite/include/graphite/Segment.h new file mode 100644 index 00000000000..41443c27f53 --- /dev/null +++ b/Build/source/libs/graphite/include/graphite/Segment.h @@ -0,0 +1,627 @@ +/*--------------------------------------------------------------------*//*:Ignore this sentence. +Copyright (C) 1999, 2001 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: Segment.h +Responsibility: Sharon Correll +Last reviewed: Not yet. + +Description: + Defines the class for a Graphite text segment. +----------------------------------------------------------------------------------------------*/ +#ifdef _MSC_VER +#pragma once +#endif +#ifndef GR_SEGMENT_INCLUDED +#define GR_SEGMENT_INCLUDED + +#include "Font.h" +#include "GrConstants.h" +#include "SegmentAux.h" + +// undo automagic DrawTextA DrawTextW stuff +// #undef DrawText + +//:End Ignore + +namespace gr +{ +class GrEngine; +class SegmentMemoryUsage; + +class IGrJustifier; +class GrTableManager; +class GrSlotStream; +class GrSlotOutput; + +/*---------------------------------------------------------------------------------------------- + A Graphite segment consists of a sequence of well-positioned glyphs all on one line, + Each glyph understands its relationship to the underlying text that was used to generate + the segment. + + Hungarian: seg +----------------------------------------------------------------------------------------------*/ +class Segment +{ + friend class GrEngine; + friend class SegmentPainter; + friend class GlyphInfo; + friend class GlyphIterator; + friend class GlyphSetIterator; + friend class SegmentMemoryUsage; + +public: + // Static methods + + // Constructors, destructors, etc. + Segment(); +// Segment(ITextSource * pgts, int ichMin, int ichLim, +// LineBrk lbStart, LineBrk lbEnd, +// bool fStartLine, bool fEndLine, bool fWsRtl); + + virtual ~Segment(); + + // Basic copy constructor: + Segment(Segment & seg); + + // For making modified copies of segments: + static Segment * LineContextSegment(Segment & seg, bool fStartLine, bool fEndLine); + static Segment * JustifiedSegment(Segment & seg, float xsNewWidth); + static Segment * WhiteSpaceSegment(Segment & seg, int newDirDepth); + + static int GetSegmentCount(); + +public: + + long IncRefCount(); + long DecRefCount(); + + Font & getFont(); + ITextSource & getText(); + float advanceWidth(); + Rect boundingRect(); + + bool rightToLeft(); + bool paraRightToLeft() { return m_fParaRtl; } + int directionDepth(bool * pfWeak = NULL); + bool setDirectionDepth(int nNewDepth); + int startCharacter(); + int stopCharacter(); + bool startOfLine(); + bool endOfLine(); + bool hasLineBoundaryContext(); + SegEnd segmentTermination(); + LineBrk startBreakWeight(); + LineBrk endBreakWeight(); + float stretch(); + float maxStretch(); + float maxShrink(); + void setTextSourceOffset(int ichMin) + { + m_ichwMin = ichMin; + } + + //GrResult changeLineEnds(bool fNewStart, bool fNewEnd); + + std::pair<GlyphIterator, GlyphIterator> glyphs(); + std::pair<GlyphSetIterator, GlyphSetIterator> charToGlyphs(toffset ich); + + // OBSOLETE: + GrResult GetCharData(int cchMax, utf16 * prgch, int * pcchRet); + GrResult GlyphToChar(int iginf, bool fFirst, int * pich); + GrResult GlyphToAllChars(int iginf, int cichMax, int * prgich, int *pcichRet); + GrResult CharToGlyph(int ich, bool fFirst, int * pigbb); + + // Not part of FW interface: + + float getRangeWidth(int ichMin, int ichLim, + bool fStartLine = true, bool fEndLine = true, bool fSkipSpace = true); + int findNextBreakPoint(int ichStart, + LineBrk lbPref, LineBrk lbWorst, float dxMaxWidth, + float * pdxBreakWidth, bool fStartLine = true, bool fEndLine = true); + + GrResult getUniscribeClusters( + int * prgigbb1stOfCluster, int cchMax, int * pcch, + bool * pfClusterStart, int cfMax, int * pcf); + + //GrResult GetGlyphsAndPositions( + // Rect rsArg, Rect rdArg, int cgidMax, int * pcgidRet, utf16 * prggid, + // float * prgxd, float * prgyd, float * prgdxdAdv); + //GrResult GetUniscribePositions( + // Rect rs, Rect rd, int cgidMax, int * pcgidRet, + // float * prgxd, float * prgyd, float * prgdxdAdv); + //GrResult GetUniscribeGlyphsAndPositions( + // Rect rsArg, Rect rdArg, int cgidMax, int * pcchRet, utf16 * prgchGlyphs, + // float * prgxd, float * prgyd, float * prgdxdAdv); + + // Other public methods: + + void Initialize(ITextSource * pgts, int ichMin, int ichLim, + LineBrk lbStart, LineBrk lbEnd, SegEnd est, + bool fStartLine, bool fEndLine, bool fWsRtl); + void DestroyContents(); + void SwapWith(Segment * pgrseg); + void ClearAltEndLineSeg(); + + ITextSource * GetString(); // client is responsible to Release() + + // The following three functions handle storing and retrieving information that + // allows us to restart a new segment following a line break. This is necessary + // in case there is some sort of contextualization across the line break. + void StoreRestartInfo(int cslotRestartBackup, std::vector<int>& vnSkipOffsets) + { + m_cslotRestartBackup = cslotRestartBackup; + m_vnSkipOffsets.resize(vnSkipOffsets.size()); + for (size_t i = 0; i < vnSkipOffsets.size(); i++) + m_vnSkipOffsets[i] = sdata8(vnSkipOffsets[i]); + } + int NextRestartBackup() + { + return m_cslotRestartBackup; + } + int RestartBackup() + { + //return (m_psegPrev)? m_psegPrev->NextRestartBackup(): 0; + return 0; + } + int SkipOffset(int ipass) + { + return int(m_vnSkipOffsets[ipass]); + } + DirCode PreviousStrongDir() + { + return m_dircPrevStrong; + } + void SetPreviousStrongDir(DirCode dirc) + { + m_dircPrevStrong = dirc; + } + DirCode PreviousTermDir() + { + return m_dircPrevTerm; + } + void SetPreviousTermDir(DirCode dirc) + { + m_dircPrevTerm = dirc; + } + + int NextSegInitBuffer(byte ** ppbDat) + { + *ppbDat = m_prgbNextSegDat; + return m_cbNextSegDat; + } + int ThisSegInitBuffer(byte ** ppbDat) + { + *ppbDat = m_prgInitDat; + return m_cbInitDat; + } + +// void SetNextSeg(Segment * psegNext) +// { +// m_psegNext = psegNext; +// } + + void SetFaceName(std::wstring stu, std::wstring stuBase) + { +// m_stuFaceName = stu; +// m_stuBaseFaceName = stuBase; +// m_fUseSepBase = (m_stuBaseFaceName.size() > 0); + } + + void SetEngine(GrEngine * pgreng); + void SetFont(Font * pfont); + void SwitchFont(Font * pfont); + GrEngine * EngineImpl(); + + void SetJustifier(IGrJustifier * pgjus); + IGrJustifier * Justifier() + { + return m_pgjus; + } + + void SetPreContext(int dich) + { + m_dichPreContext = dich; + } + + //void SetToBaseFont(IGrGraphics * pgg); + //void RestoreFont(IGrGraphics * pgg); + + void SetUpOutputArrays(Font * pfont, GrTableManager * ptm, + GrSlotStream * psstrmFinal, + int cchwUnderlying, int csloutSurface, gid16 chwLB, + TrWsHandling twsh, bool fParaRtl, int nDirDepth, + bool fEmpty = false); + void RecordSurfaceAssoc(int ichw, int islot, int nDir); + void RecordLigature(int ichwUnder, int islotSurface, int iComponent); + void AdjustForOverlapsWithPrevSeg(); + void MarkSlotInPrevSeg(int ichw, int islot); + void MarkSlotInNextSeg(int ichw, int islot); + + void CleanUpAssocsVectors() + { + for (int iv = 0; iv < m_ichwAssocsLim - m_ichwAssocsMin; iv++) + { + std::vector<int> * pvislout = m_prgpvisloutAssocs[iv]; + if (pvislout->size() <= 1) + { + delete pvislout; + *(m_prgpvisloutAssocs + iv) = NULL; + } + } + } + + GrSlotOutput * OutputSlot(int islout); + + void RecordInitializationForNextSeg(int cbNextSegDat, byte * pbNextSegDat) + { + m_cbNextSegDat = cbNextSegDat; + m_prgbNextSegDat = new byte[m_cbNextSegDat]; + std::copy(pbNextSegDat, pbNextSegDat + cbNextSegDat, m_prgbNextSegDat); + } + void RecordInitializationForThisSeg(int cbDat, byte * pbDat) + { + m_cbInitDat = cbDat; + if (cbDat == 0) + m_prgInitDat = NULL; + else + { + m_prgInitDat = new byte[m_cbInitDat]; + std::copy(pbDat, pbDat + cbDat, m_prgInitDat); + } + } + + void SetWidths(float dxsVisWidth, float dxsTotalWidth) + { + m_dxsVisibleWidth = dxsVisWidth; + m_dxsTotalWidth = dxsTotalWidth; + } + + void SetLayout(LayoutEnvironment & layout) + { + m_layout.setStartOfLine(layout.startOfLine()); + m_layout.setEndOfLine(layout.endOfLine()); + m_layout.setBestBreak(layout.bestBreak()); + m_layout.setWorstBreak(layout.worstBreak()); + m_layout.setRightToLeft(layout.rightToLeft()); + m_layout.setTrailingWs(layout.trailingWs()); + m_layout.setPrevSegment(layout.prevSegment()); + m_layout.setJustifier(layout.justifier()); + m_layout.setLoggingStream(layout.loggingStream()); + m_layout.setDumbFallback(layout.dumbFallback()); + } + LayoutEnvironment & Layout() + { + return m_layout; + } + + bool Erroneous() + { + return m_fErroneous; + } + void SetErroneous(bool f) + { + m_fErroneous = f; + } + + void FixTermination(SegEnd est) + { + m_est = est; + } + + // Convert from em-units to logical units. + float EmToLogUnits(int m); + + Rect ComponentRect(GrSlotOutput * pslout, int icomp); + + void ClusterMembersForGlyph(int islout, int disloutCluster, std::vector<int> & visloutRet); + + // for transduction logging: + // implementations are empty unless TRACING is defined + void LogUnderlyingToSurface(GrTableManager * ptman, std::ostream & strmOut, + GrCharStream * pchstrm); + void LogSurfaceToUnderlying(GrTableManager * ptman, std::ostream & strmOut); + void LogXmlUnderlyingToSurface(std::ostream & strmOut, GrTableManager * ptman, + GrCharStream * pchstrm, int nIndent); + void LogXmlSurfaceToUnderlying(std::ostream & strmOut, GrTableManager * ptman, + GrCharStream * pchstrm, int nIndent); + + // calculate memory usage + void calculateMemoryUsage(SegmentMemoryUsage & smu); + +protected: + // Member variables: + long m_cref; // standard COM ref count + + ITextSource * m_pgts; // the string we are a segment of + int m_dichwLim; // number of characters officially in this segment + int m_ichwMin; // first character relative to the text-source + + Font * m_pfont; + GrEngine * m_preneng; + + bool m_fErroneous; // an error occurred in generating this segment + + IGrJustifier * m_pgjus; + + LayoutEnvironment m_layout; + + bool m_fWsRtl; // writing system direction + bool m_fParaRtl; // paragraph direction; redundant with layout? + + TrWsHandling m_twsh; // // redundant with layout? + int m_nDirDepth; // segment direction (white-space-only segments can switch) + + byte * m_prgbNextSegDat; // for initializing the following segment + int m_cbNextSegDat; // length of above buffer + + byte * m_prgInitDat; // what was used to initialize this segment + int m_cbInitDat; + + int m_dichPreContext; // what part of this segment affects the previous; + // not really used for anything right now + +// Segment * m_psegPrev; // OBSOLETE +// Segment * m_psegNext; + + // Font information: +// std::wstring m_stuFaceName; +// std::wstring m_stuBaseFaceName; +// bool m_fUseSepBase; + +// float m_pixHeight; // character height of font in pixels (NOT = ascent + descent) +// bool m_fBold; +// bool m_fItalic; + + LineBrk m_lbStart; + LineBrk m_lbEnd; + + bool m_fStartLine; // redundant with layout? + bool m_fEndLine; // redundant with layout? + + SegEnd m_est; + + //Segment * m_psegAltEndLine; // segment having the alternate m_fEndLine value + + int m_mFontEmUnits; + float m_dysFontAscent; + float m_dysFontDescent; + float m_xysEmSquare; // em-square of the font in display units +// float m_xsDPI; // DPI of device on which segment was measured +// float m_ysDPI; + + float m_dxsStretch; // difference between actual and natural width + float m_dxsWidth; // width in absence of any stretch. -1 if not computed. + float m_dysHeight; + float m_dysAscent; // distance from common baseline to top of this segment, + // including extra ascent + + float m_dysXAscent; // extra for this renderer, beyond what is standard for the font + float m_dysXDescent; + + float m_dysAscentOverhang; // extra height above official top of segment; >= 0 + float m_dysDescentOverhang; // extra height below bottom of segment; <= 0; + float m_dxsLeftOverhang; // <= 0 + float m_dxsRightOverhang; + + float m_dxsVisibleWidth; // not including trailing white space + float m_dxsTotalWidth; // including trailing white space + + int m_isloutVisLim; // lim of visible stuff (to handle trailing ws underlines) + + float m_dysOffset; + + // Index of the first item in the before/after arrays and the ligature/component arrays, + // relative to the start of the segment. Normally == 0, but will be some negative number + // if there are slots "borrowed" from the previous segment (officially located in the + // previous segment but rendered in this one). + int m_ichwAssocsMin; + + // 1 + index of last item in the before/after arrays and the ligature/component arrays, + // relative to the start of the segment. Normally == m_dichwLim, but will be + // larger if there are slots "borrowed" from the following segment. + int m_ichwAssocsLim; + + // Underlying-to-surface associations: + int * m_prgisloutBefore; // logical first + int * m_prgisloutAfter; // logical last + std::vector<int> ** m_prgpvisloutAssocs; // all; used by range selections + + int * m_prgisloutLigature; // similar to above, index of associated ligature, or kNegInfinity + + sdata8 * m_prgiComponent; // component of the ligature that the corresponding character + // represents; only meaningful if corresponding item in + // m_prgisloutLigature is set + +// GrSlotStream * m_psstrm; // TODO: rework to remove this + int m_cslout; + GrSlotOutput * m_prgslout; // final output slots + u_intslot * m_prgnSlotVarLenBuf; // var-length buffer for slots--one big buffer managed by the + // segment, but pointed to by the slots + +// int m_cnUserDefn; // this information is not stored in the segment itself + int m_cnCompPerLig; +// int m_cnFeat; // this information is not stored in the segment itself + + int m_cginf; + int m_isloutGinf0; // islout index for m_prgginf[0]; + GlyphInfo * m_prgginf; + + // Data structures to hold glyphs for rendering: +////#include "GrSegmentPlatform.h" + + // For initializing the following segment: + int m_cslotRestartBackup; // the number of slots in the underlying + // input that need to be reprocessed when starting + // the next segment + + std::vector<sdata8> m_vnSkipOffsets; // skip offset for each pass when restarting + + DirCode m_dircPrevStrong; // previous strong directionality code + DirCode m_dircPrevTerm; // previous terminator code, if any + + + // Other protected methods: + + void InitLineContextSegment(bool fStartLine, bool fEndLine); + void InitWhiteSpaceSegment(int nNewDepth); + + void ComputeDimensions(); + + void SetUpGlyphInfo(GrTableManager * ptman, GrSlotStream * psstrmFinal, + gid16 chwLB, int nDirDepth, int islotMin, int cslot); + void SetUpLigInfo(GrTableManager * ptman, GlyphInfo & ginf, GrSlotOutput * pslout); + + void InitBeforeArrayFromPrevSeg(); // obsolete + void AdjustBeforeArrayFromPrevSeg(); + void AdjustAfterArrayFromNextSeg(); + void EnsureSpaceAtLineBoundaries(int ichwUnder); + + int LogicalSurfaceToUnderlying(int islout, + float xsOffset, float ysOffset, + float dxsGlyphWidth = 0, float dysGlyphHeight = 0, bool * pfAfter = NULL); + int LogicalSurfaceToUnderlying(int islout, bool fBefore); + int PhysicalSurfaceToUnderlying(int iginf, + float xsOffset, float xyOffset, + float dxsGlyphWidth = 0, float dysGlyphHeight = 0, bool * pfAfter = NULL); + int PhysicalSurfaceToUnderlying(int iginf, bool fBefore); + int UnderlyingToLogicalSurface(int ichw, bool fBefore); + int UnderlyingToPhysicalSurface(int ichw, bool fBefore); + int LogicalToPhysicalSurface(int islout); + void UnderlyingToPhysicalAssocs(int ichw, std::vector<int> & viginf); + std::vector<int> UnderlyingToLogicalAssocs(int ichw); + int UnderlyingToLogicalInThisSeg(int ichw); + bool SameSurfaceGlyphs(int ichw1, int ichw2); + + void ShiftGlyphs(float dxsShift); + + float GlyphLeftEdge(int iginf); + + int DirLevelOfChar(int ichw, bool fBefore); + int CharIsRightToLeft(int ichw, bool fBefore); + int SlotIsRightToLeft(GrSlotOutput * pslout); + int TopDirLevel() + { + if (m_fWsRtl) + return 1; + else + return 0; + } + + void AssertValidClusters(GrSlotStream * psstrm); + + void MergeUniscribeCluster( + std::vector<int> & visloutBefore, std::vector<int> & visloutAfter, + int ich1, int ich2); + + int GlyphHit(float xsClick, float ysClick); + int SelectBb(std::vector<int> & viginf, bool fRTL); + + int RightMostGlyph(); + int LeftMostGlyph(); + + void ComputeOverhangs(float * pdysVisAscent, float * pdysNegVisDescent, + float * pdxsVisLeft, float * pdxsVisRight); + +public: + LineBrk getBreakWeight(int ich, bool fBreakBefore = false); + + // Platform-specific routines: +protected: + //void ShiftGlyphsPlatform(float dxsShift); + //bool SetDirectionDepthPlatform(int nNewDepth); + + //void InitializePlatform(); + //void DestroyContentsPlatform(); + //GrResult GetGlyphsAndPositionsPlatform(float xs, float ys, + // Rect rsArg, Rect rdArg, + // utf16 * prgchGlyphs, float * prgxd, float * prgyd, float * prgdxdAdv); + //void SetUpOutputArraysPlatform(GrTableManager * ptman, gid16 chwLB, int nDirDepth, + // int islotMin, int cslot); + + // Temporary - for WinSegmentPainter +public: + int CSlout() + { + return m_cslout; + } + gid16 LBGlyphID(); + float AscentOffset() + { + if (m_dysAscent == -1) + ComputeDimensions(); + return m_dysAscent - m_dysFontAscent; + } +}; + + +//:>******************************************************************************************** +//:> The purpose of these subclasses is simply to provide meaningful names for the +//:> constructors. Instances of these classes are in every way equivalent to Segment. +//:>******************************************************************************************** + +/*---------------------------------------------------------------------------------------------- + Creating a LineFillSegment fits as much of the text on the line as possible, + finding a reasonable break point if necessary. +----------------------------------------------------------------------------------------------*/ +class LineFillSegment : public Segment +{ +public: + LineFillSegment( + Font * pfont, + ITextSource * pts, + LayoutEnvironment * playout, + toffset ichStart, + toffset ichStop, + float maxWidth, + bool fBacktracking = false); +protected: + // Default constructor: + LineFillSegment() : Segment() + { + } +}; + +/*---------------------------------------------------------------------------------------------- + Creating a RangeSegment makes a segment representing the given range of characters, or + the entire text-source. +----------------------------------------------------------------------------------------------*/ +class RangeSegment : public Segment +{ +public: + RangeSegment( + Font * pfont, + ITextSource * pts, + LayoutEnvironment * playout, + toffset ichStart = 0, + toffset ichStop = kPosInfinity, + Segment * psegInitLike = NULL); +}; + +/*---------------------------------------------------------------------------------------------- + The JustSegmentAux class is used by the factory method that creates a justified segment. + It is called JustSegmentAux to avoid conflicting with the factory method. +----------------------------------------------------------------------------------------------*/ +class JustSegmentAux : public Segment +{ +public: + JustSegmentAux( + Font * pfont, + ITextSource * pts, + LayoutEnvironment * playout, + toffset ichStart, + toffset ichStop, + float xsNaturalWidth, + float xsJustifiedWidth, + Segment * psegInitLike = NULL); +}; + +} // namespace gr + +#if defined(GR_NO_NAMESPACE) +using namespace gr; +#endif + +#endif // !GR_SEGMENT_INCLUDED |