summaryrefslogtreecommitdiff
path: root/Build/source/libs/graphite/src/segment/GrTableManager.h
blob: e0306c832c79b8082a5220b823b8ec11c2097125 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
/*--------------------------------------------------------------------*//*:Ignore this sentence.
Copyright (C) 1999 - 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: GrTableManager.h
Responsibility: Sharon Correll
Last reviewed: Not yet.

Description:
    The GrTableManager class.
----------------------------------------------------------------------------------------------*/
#ifdef _MSC_VER
#pragma once
#endif
#ifndef GR_TABLEMAN_INCLUDED
#define GR_TABLEMAN_INCLUDED

#include <cassert>
//:End Ignore

namespace gr
{

class Font;

/*----------------------------------------------------------------------------------------------
	There is a single instance of Engine State that keeps track of the state of the processing
	for a single segment generation.

	Hungarian: engst
----------------------------------------------------------------------------------------------*/
class EngineState
{
	friend class GrTableManager;
	friend class FontMemoryUsage;

public:
	EngineState();
	void Initialize(GrEngine *, GrTableManager *);

	~EngineState();
	void DestroySlotBlocks();

	void InitForNewSegment(GrTableManager * ptman);

	void CreateEmpty();

	GrEngine * Engine();
	GrTableManager * TableManager();

	void CreateSlotStreams();

	GrSlotStream * InputStream(int ipass)
	{
		Assert(ipass > 0); // the char stream serves as input to the zeroth pass
		return m_prgpsstrm[ipass - 1];
	}

	//	Return the stream that serves as output to the given pass.
	GrSlotStream * OutputStream(int ipass)
	{
		Assert(ipass < m_cpass);
		return m_prgpsstrm[ipass];
	}

	GrSlotState * AnAdjacentSlot(int ipassArg, int islotArg);

	GrResult GetGlyphAttrForJustification(int iGlyph, int jgat, int nLevel, float * pxysValueRet);
	GrResult GetGlyphAttrForJustification(int iGlyph, int jgat, int nLevel, int * pxysValueRet);
	GrResult SetGlyphAttrForJustification(int iGlyph, int jgat, int nLevel, float xysValue);
	GrResult SetGlyphAttrForJustification(int iGlyph, int jgat, int nLevel, int xysValue);

	enum { kSlotBlockSize = 50 };	// number of slots to allocate in a block

	void InitPosCache()
	{
		m_islotPosNext = -1;
		m_xsPosXNext = 0;
		m_ysPosYNext = 0;
		m_dxsTotWidthSoFar = 0;
		m_dxsVisWidthSoFar = 0;
	}

	void SetFont(Font * pfont)
	{
		m_pfont = pfont;
	}
	Font * GetFont()
	{
		return m_pfont;
	}

	bool StartLineContext()
	{
		return m_fStartLineContext;
	}
	bool EndLineContext()
	{
		return m_fEndLineContext;
	}
	void SetStartLineContext(bool f)
	{
		m_fStartLineContext = f;
	}
	void SetEndLineContext(bool f)
	{
		m_fEndLineContext = f;
	}

	void SetInitialLB(bool f = true)
	{
		m_fInitialLB = f;
	}

	void SetFinalLB(bool f = true)
	{
		m_fFinalLB = f;
	}

	void SetInsertedLB(bool f = true)
	{
		m_fInsertedLB = f;
	}

	bool HasInitialLB()
	{
		 return m_fInitialLB;
	}
	bool HasInsertedLB()
	{
		return m_fInsertedLB;
	}
	bool HasFinalLB()
	{
		 return m_fFinalLB;
	}

	void SetExceededSpace(bool f = true)
	{
		m_fExceededSpace = f;
	}

	bool ExceededSpace()
	{
		return m_fExceededSpace;
	}

	void SetHitHardBreak(bool f = true)
	{
		 m_fHitHardBreak = f;
	}

	bool HitHardBreak()
	{
		return m_fHitHardBreak;
	}

	void SetRemovedTrWhiteSpace(bool f = true)
	{
		m_fRemovedWhtsp = f;
	}

	bool RemovedTrWhiteSpace()
	{
		return m_fRemovedWhtsp;
	}

	bool WhiteSpaceOnly()
	{
		return (m_twsh == ktwshOnlyWs);
	}

	bool ParaRightToLeft()
	{
		return m_fParaRtl;
	}

	//int PrevPassMaxBackup(int ipass)
	//{
	//	if (ipass == 0)
	//		return 0;
	//	return Pass(ipass - 1)->MaxBackup();
	//}

	DirCode InitialStrongDir()
	{
		return m_dircInitialStrongDir;
	}
	DirCode InitialTermDir()
	{
		return m_dircInitialTermDir;
	}

	void InitializeStreams(GrTableManager * ptman, GrCharStream * pchstrm,
		int cbPrev, byte * pbPrevSegDat, bool fNeedFinalBreak, int * pislotFinalBreak);
	int LbSlotToSegLim(int islot, GrCharStream * pchstrm, int cpassLB);
	int TraceStreamZeroPos(int islotFinal, int nTopDir);

	float EmToLogUnits(int m);
	int LogToEmUnits(float xys);
	bool GPointToXY(gid16 chwGlyphID, int nGPoint, float * xs, float * ys);

	void AddJWidthToAdvance(GrSlotStream * psstrm, GrSlotState ** ppslot, int islot,
		GrSlotState ** ppslotLast, GrSlotState ** ppslotLastBase);

	//	Memory management for slots:
	void NewSlot(gid16 gID, GrFeatureValues fval, int ipass, int ichwSegOffset, int nUnicode,
		GrSlotState **);
	void NewSlot(gid16 gID, GrSlotState * pslotFeat, int ipass, int ichwSegOffset,
		GrSlotState **);
	void NewSlot(gid16 gID, GrSlotState * pslotFeat, int ipass, GrSlotState **);
	void NewSlotCopy(GrSlotState * pslotCopyFrom, int ipass,
		GrSlotState ** pslotRet);
protected:
	void NextSlot(GrSlotState ** ppslot);

protected:
	GrTableManager * m_ptman;

	int m_cFeat;
	int m_cCompPerLig;
	int m_cUserDefn;

	int m_jmodi;			// justification mode
	int m_ipassJustCalled;	// pass after which justification routine was called;
							// -1 if we are not in the midst of interacting with the
							// GrJustifier

	//	Pointer to font
	Font * m_pfont;

	bool m_fStartLineContext;	// true if there was a rule that ran over the initial LB
	bool m_fEndLineContext;		// true if there was a rule that ran over the final LB

	//	the number of slots inserted in the first stream before the official beginning
	//	of the segment, including any initial line break
	int m_cslotPreSeg;

	//	List of allocated GrSlotStates; hungarian slotblk = prgslot
	std::vector<GrSlotState *> m_vslotblk;
	std::vector<u_intslot *> m_vprgnSlotVarLenBufs; // corresponding var-length blocks
	int m_islotblkCurr;
	int m_islotNext;

	//	Directionality codes from previous segment; these are used by the bidi algorithm
	//	at the initial line-break character.
	DirCode m_dircInitialStrongDir;
	DirCode m_dircInitialTermDir;

	LineBrk m_lbPrevEnd;

	//	All of the following 3 are true only when there is an actual LB glyph in the stream
	bool m_fInitialLB;		// is there is an initial LB (an actual LB glyph--in all streams)
	bool m_fFinalLB;		// is there is a final LB (in all streams--true when we've hit
							// the end of the input and end-of-line is true)
	bool m_fInsertedLB;		// is there is a final LB inserted in the output of LB pass
							// (true when we've backtracked)

	bool m_fExceededSpace;	// true if we backtracked due to exceeding space; false if we
							// haven't backtracked, or we did so for some other reason
							// (eg, omitting trailing whitespace)

	bool m_fHitHardBreak;	// true if we encountered a hard-break in the input stream
							// (before the natural end of the segment)

	bool m_fRemovedWhtsp;	// true if we've hit trailing whitespace characters that we've
							// removed

	TrWsHandling m_twsh;	// white-space handling
	bool m_fParaRtl;		// paragraph direction

	float m_dxsShrinkPossible;

	//	The final positioning pass is where we are going to do most of the positioning.
	//	Cache the intermediate results so we don't have to calculate from the beginning of
	//	the segment every time.
	int m_islotPosNext;	// where to continue calculating positions in final output stream
						// (one past the last base that was calculated)
	float m_xsPosXNext;
	float m_ysPosYNext;
	float m_dxsTotWidthSoFar;
	float m_dxsVisWidthSoFar;

	int m_cpass;	// number of passes

	//	array of pass-state objects
	PassState * m_prgzpst;

	//	array of slot streams which are output of passes (input of zeroth
	//	pass is the character stream, not a slot stream):
	GrSlotStream ** m_prgpsstrm;
			//	For instance, a simple set of passes might look like this:
			//		CharStream
			//			GlyphGenPass		pass 0
			//		SlotStream				stream 0
			//			SubPass				pass 1
			//		SlotStream				stream 1
			//			PosPass				pass 2
			//		SlotStream				stream 2
			//
			//		m_cpass = 3

}; // end of class EngineState

/*----------------------------------------------------------------------------------------------
	There is a single instance of GrTableManager that handle the interactions between
	passes, including the demand-pull mechanism.

	Hungarian: tman
----------------------------------------------------------------------------------------------*/

class GrTableManager {
	friend class FontMemoryUsage;

public:
	//	Constructor & destructor:
	GrTableManager(GrEngine * pgreng)
		:	m_cpass(0),
			m_fBidi(false),
			m_prgppass(NULL),
			m_pgreng(pgreng)
	{
		Assert(pgreng);
	}

	~GrTableManager();

	bool CreateAndReadPasses(GrIStream & grstrm, int fxdSilfVersion, int fxdRuleVersion,
		int cpassFont, long lSubTableStart, int * rgnPassOffsets,
		int ipassSub1Font, int ipassPos1Font, int ipassJust1Font, byte ipassPostBidiFont);

	void CreateEmpty();

	GrEngine * Engine();
	EngineState * State();

	void Run(Segment * psegNew, Font * pfont, GrCharStream * pchstrm, 
		IGrJustifier * pgjus, int jmodi,
		LayoutEnvironment & layout,
		int ichStop, float dxWidth, float dxUnjustified,
		bool fNeedFinalBreak, bool fMoreText, int ichFontLim,
		bool fInfiniteWidth, bool fWidthIsCharCount,
		int ichwCallerBtLim,
		int nDirDepth, SegEnd estJ);

	GrPass* Pass(int ipass)
	{
		Assert(ipass >= 0);
		return m_prgppass[ipass];
	}

	int NumberOfPasses()
	{
		return m_cpass;
	}

	int NumberOfLbPasses()
	{
		return m_cpassLB;
	}

	bool HasBidiPass()
	{
		return m_fBidi;
	}

	int FirstPosPass()
	{
		return m_ipassPos1;
	}

	void StorePassStates(PassState * rgzpst);

	//	Return the stream that serves as input to the given pass.
	GrSlotStream * InputStream(int ipass)
	{
		return m_engst.InputStream(ipass);
	}
	GrSlotStream * OutputStream(int ipass)
	{
		return m_engst.OutputStream(ipass);
	}

	void UnwindAndReinit(int islotNewBreak);

public:
	int InternalJustificationMode()
	{
		return m_engst.m_jmodi;
	}

	bool ShouldLogJustification()
	{
		return (m_engst.m_jmodi != kjmodiNormal);
	}

	int PrevPassMaxBackup(int ipass)
	{
		if (ipass == 0)
			return 0;
		return Pass(ipass - 1)->MaxBackup();
	}

	//	Forward to the engine itself
	gid16 GetGlyphIDFromUnicode(int nUnicode);
	gid16 ActualGlyphForOutput(utf16 chwGlyphID);
	GrGlyphTable * GlyphTable();

	gid16 LBGlyphID();

	gid16 GetClassGlyphIDAt(int nClass, int nIndex);
	int GetIndexInGlyphClass(int nClass, gid16 chwGlyphID);
	size_t NumberOfGlyphsInClass(int nClass);

	void SetSlotAttrsFromGlyphAttrs(GrSlotState * pslot);

	int NumFeat();
	int DefaultForFeatureAt(int ifeat);
	GrFeature * FeatureWithID(featid nID, int * pifeat);
	GrFeature * Feature(int ifeat);
	void DefaultsForLanguage(isocode lgcode,
		std::vector<featid> & vnFeats, std::vector<int> & vnValues);

	bool RightToLeft();
	int TopDirectionLevel();

	float VerticalOffset();

	int NumUserDefn();
	int NumCompPerLig();

	int ComponentIndexForGlyph(gid16 chwGlyphID, int nCompID);
	int GlyphAttrValue(gid16 chwGlyphID, int nAttrID);

	//	---

	bool LoggingTransduction();

	float EmToLogUnits(int m);
	int LogToEmUnits(float xys);
	bool GPointToXY(gid16 chwGlyphID, int nGPoint, float * xs, float * ys);

	void CalcPositionsUpTo(int ipass, GrSlotState * pslotLast,
		float * pxsWidth, float * pxsVisibleWidth);

	void InitPosCache()
	{
		m_engst.InitPosCache();
	}

	bool IsWhiteSpace(GrSlotState * pslot);

	//	For transduction logging:
	bool WriteTransductionLog(std::ostream * pstrmLog,
		GrCharStream * pchstrm, Segment * psegRet, int cbPrevSetDat, byte * pbPrevSegDat);
	bool WriteAssociationLog(std::ostream * pstrmLog,
		GrCharStream * pchstrm, Segment * psegRet);
	bool WriteXmlLog(std::ostream * pstrmLog,
		GrCharStream * pchstrm, Segment * psegRet, int cbPrevSegDat, byte * pbPrevSegDat);
	bool WriteXmlAssocLog(std::ostream * pstrmLog,
		GrCharStream * pchstrm, Segment * psegRet);

#ifdef TRACING
	void WriteXductnLog(std::ostream & strmOut, GrCharStream * pchstrm, Segment * psegRet,
		int cbPrevSegDat, byte * pbPrevSegDat);
	//bool LogFileName(std::string & staFile);
	void LogUnderlying(std::ostream & strmOut, GrCharStream * pchstrm, int cchwBackup);
	void LogPass1Input(std::ostream & strmOut);
	void LogPassOutput(std::ostream & strmOut, int ipass, int cslotSkipped);
	void LogAttributes(std::ostream & strmOut, int ipass, bool fJustWidths = false);
	void LogFinalPositions(std::ostream & strmOut);
	void LogUnderlyingHeader(std::ostream & strmOut, int ichwMin,
		int ichwLim, int cchwBackup, int * prgichw16bit);
	void LogSlotHeader(std::ostream & strmOut, int cslot,
		int cspPerSlot, int cspLeading, int islotMin = 0);
	void LogSlotGlyphs(std::ostream & strmOut, GrSlotStream * psstrm);
	void SlotAttrsModified(int ipass, bool * rgfMods, bool fPreJust, int * pccomp, int *pcassoc);
	void LogInTable(std::ostream & strmOut, int n);
	void LogInTable(std::ostream & strmOut, float n);
	void LogHexInTable(std::ostream & strmOut, gid16 chw, bool fPlus = false);
	void LogDirCodeInTable(std::ostream & strmOut, int dirc);
	void LogBreakWeightInTable(std::ostream & strmOut, int lb);

	void WriteXmlLogAux(std::ostream & strmOut,
		GrCharStream * pchstrm, Segment * psegRet, int cbPrevSegDat, byte * pbPrevSegDat);
	void LogXmlUnderlying(std::ostream & strmOut, GrCharStream * pchstrm, int cchwBackup, size_t nIndent);
	void 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);
	void LogXmlPass(std::ostream & strmOut, int ipass, int cslotSkipped, int nIndent);

	void LogXmlTagOpen(std::ostream & strmOut, std::string strTag, size_t nIndent, bool fContent);
	void LogXmlTagPostAttrs(std::ostream & strmOut, bool fContent);
	void LogXmlTagClose(std::ostream & strmOut, std::string strTag, size_t nIndent, bool fContent);
	void LogXmlTagAttr(std::ostream & strmOut, std::string strAttr, int nValue, size_t nIndent = 0);
	void LogXmlTagAttr(std::ostream & strmOut, std::string strAttr, const char * szValue, size_t nIndent = 0);
	void LogXmlTagAttrHex(std::ostream & strmOut, std::string strAttr, int nValue, size_t nIndent = 0);
	std::string HexString(int n1, int n2, int n3, int n4, int n5, int n6);
	std::string HexString(std::vector<int>);
	void LogXmlTagColor(std::ostream & strmOut, std::string strAttr, int clrValue, bool fBack,
		size_t nIndent = 0);
	void LogXmlDirCode(std::ostream & strmOut, std::string strAttr, int dircValue, size_t nIndent = 0);
	void LogXmlBreakWeight(std::ostream & strmOut, std::string strAttr, int dircValue,
		size_t nIndent = 0);
	void LogXmlComment(std::ostream & strmOut, std::string strComment, size_t nIndent = 0);

#endif // TRACING

protected:
	void InitNewSegment(Segment * psegNew, Font * pfont, GrCharStream * pchstrm, IGrJustifier * pgjus,
		int islotStream0Break, int islotSurfaceBreak, bool fStartLine, bool fEndLine, int ichFontLim,
		LineBrk lbEnd, SegEnd est, int * dichSegLen);

	void InitSegmentAsEmpty(Segment * psegNew, Font * pfont, GrCharStream * pchstrm,
		bool fStartLine, bool fEndLine);

	void InitSegmentToDelete(Segment * psegNew, Font * pfont, GrCharStream * pchstrm);

	int ChunkInPrev(int ipass, int islot, GrCharStream * pchstrm);

	bool Backtrack(int * islotPrevLB,
	   LineBrk * plbPref, LineBrk lbMax, TrWsHandling, bool fMoreText,
	   int ichwCallerBtLim, LineBrk * plbFound);

	LineBrk IncLineBreak(LineBrk lb);

	void InitializeForNextSeg(Segment* pseg,
		int islotStream0Break, int islotSurfaceBreak, LineBrk lbEnd,
		bool fNextSegNeedsContext, GrCharStream * pchstrm);

	void SetFinalPositions(Segment * pseg, bool fWidthIsCharCount);
	void RecordAssocsAndOutput(Font * pfont, Segment * pseg,
		TrWsHandling twsh, bool fParaRtl, int nDirDepth);

	void CalculateAssociations(Segment * pseg, int csloutSurface);
	void AdjustAssocsForOverlaps(Segment * pseg);

	void UnstretchTrailingWs(GrSlotStream * psstrm, int iGlyphLim);
	void CallJustifier(IGrJustifier * pgjus, int ipassCurr, float dxUnjustified, float dxJustified,
		bool fEndLine);

	void DetermineShrink(IGrJustifier * pgjus, int ipass);

protected:
	//	Instance variables:

	int m_cpass;	//	number of passes; zero-th pass is Unicode character -> glyph ID mapping;
					//	Note thatwe always have one positioning pass to measure things even
					//	if there are no tables to run.

	int m_cpassLB;		// number of line-break passes
	int m_ipassPos1;	// first positioning pass
	int m_ipassJust1;	// first justification pass (== m_ipassPos1 if none)

	bool m_fBidi;	//	is there a bidi pass?

	//	array of passes:
	GrPass ** m_prgppass;

	//	Pointer back to Graphite engine, to give access to global constants and tables.
	GrEngine * m_pgreng;

	//	State of processing.
	EngineState m_engst;

	bool m_fLogging;

public:
	//	For test procedures:
	void SetUpTest(std::wstring);

protected:
	void TempDebug();
	int SurfaceLineBreakSlot(int ichw, GrCharStream * pchstrm, bool fInitial);
	std::wstring ChunkDebugString(int ipass);
};	// end of class GrTableManager

} // namespace gr


#endif // !GR_TABLEMAN_INCLUDED