1 /* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */
2 /* AbiWord
3  * Copyright (C) 2004 Tomas Frydrych
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301 USA.
19  */
20 
21 #include "ut_assert.h"
22 #include "ut_debugmsg.h"
23 #include "ut_OverstrikingChars.h"
24 #include "ut_TextIterator.h"
25 #include "ut_string.h"
26 #include "gr_RenderInfo.h"
27 
clear()28 void GR_Itemization::clear()
29 {
30 	m_vOffsets.clear();
31 
32 	UT_VECTOR_PURGEALL(GR_Item *, m_vItems);
33 	m_vItems.clear();
34 }
35 
36 
37 //////////////////////////////////////////////////////////////////////////////////////////
38 //
39 // implementation of GRXPRenderInfo
40 //
41 
42 #define GRIXP_STATIC_BUFFER_SIZE 256
43 
44 UT_sint32       GR_XPRenderInfo::s_iClassInstanceCount = 0;
45 UT_UCS4Char *   GR_XPRenderInfo::s_pCharBuff           = NULL;
46 UT_sint32 *     GR_XPRenderInfo::s_pWidthBuff          = NULL;
47 UT_sint32       GR_XPRenderInfo::s_iBuffSize           = 0;
48 UT_sint32 *     GR_XPRenderInfo::s_pAdvances           = NULL;
49 GR_RenderInfo * GR_XPRenderInfo::s_pOwner              = NULL;
50 
GR_XPRenderInfo(GR_ScriptType type)51 GR_XPRenderInfo::GR_XPRenderInfo(GR_ScriptType type)
52 		:GR_RenderInfo(type),
53 		 m_pChars(NULL),
54 		 m_pWidths(NULL),
55 		 m_iBufferSize(0),
56 		 m_pSegmentOffset(NULL),
57 		 m_iSegmentCount(0),
58 		 m_iSpaceWidthBeforeJustification(0xfffffff), // note one less 'f'
59 		 m_iTotalLength(0)
60 {
61 	_constructorCommonCode();
62 }
63 #if 0
64 GR_XPRenderInfo::GR_XPRenderInfo(UT_UCS4Char *pChar,
65 				  UT_sint32 * pAdv,
66 				  UT_uint32 offset,
67 				  UT_uint32 len,
68 				  UT_uint32 iBufferSize,
69 				  GR_ScriptType type)
70 		:GR_RenderInfo(type),
71 		 m_pChars(pChar),
72 		 m_pWidths(NULL),
73 		 m_iBufferSize(iBufferSize),
74 		 m_pSegmentOffset(NULL),
75 		 m_iSegmentCount(0),
76 		 m_iSpaceWidthBeforeJustification(0xfffffff) // not one less 'f'
77 {
78 	m_iOffset = offset;
79 	m_iLength = len;
80 	xxx_UT_DEBUGMSG(("GR_XPRender %x constructed \n"));
81 	_constructorCommonCode();
82 };
83 #endif
_constructorCommonCode()84 void GR_XPRenderInfo::_constructorCommonCode()
85 {
86 	if(!s_iClassInstanceCount)
87 	{
88 		s_pCharBuff = new UT_UCS4Char [GRIXP_STATIC_BUFFER_SIZE];
89 		UT_return_if_fail(s_pCharBuff);
90 
91 		s_pWidthBuff = new UT_sint32 [GRIXP_STATIC_BUFFER_SIZE];
92 		UT_return_if_fail(s_pWidthBuff);
93 
94 		s_pAdvances = new UT_sint32 [GRIXP_STATIC_BUFFER_SIZE];
95 		UT_return_if_fail(s_pAdvances);
96 
97 		s_iBuffSize = GRIXP_STATIC_BUFFER_SIZE;
98 	}
99 
100 	s_iClassInstanceCount++;
101 }
102 
103 
~GR_XPRenderInfo()104 GR_XPRenderInfo::~GR_XPRenderInfo()
105 {
106 	--s_iClassInstanceCount;
107 	if(!s_iClassInstanceCount)
108 	{
109 		delete [] s_pCharBuff;    s_pCharBuff = NULL;
110 		delete [] s_pWidthBuff;   s_pWidthBuff = NULL;
111 		delete [] s_pAdvances;    s_pAdvances = NULL;
112 
113 		s_pOwner = NULL;
114 	}
115 	xxx_UT_DEBUGMSG(("Deleting GR_XPRenderInfo %x \n",this));
116     delete [] m_pChars;
117 	delete [] m_pWidths;
118 	m_pChars = NULL;
119 	m_pWidths = NULL;
120 }
121 
122 /*!
123     append data represented by ri to ourselves
124 
125     NB: combine the justification information
126 
127 */
append(GR_RenderInfo & ri,bool bReverse)128 bool GR_XPRenderInfo::append(GR_RenderInfo &ri, bool bReverse)
129 {
130 	GR_XPRenderInfo & RI = (GR_XPRenderInfo &) ri;
131 
132 	if((m_iBufferSize <= m_iLength + RI.m_iLength) || (bReverse && (m_iLength > RI.m_iLength)))
133 	{
134 		xxx_UT_DEBUGMSG(("GR_RenderInfo::append: reallocating span buffer\n"));
135 		m_iBufferSize = m_iLength + RI.m_iLength + 1;
136 		UT_UCS4Char * pSB = new UT_UCS4Char[m_iBufferSize];
137 		UT_sint32 * pWB = new UT_sint32[m_iBufferSize];
138 
139 		UT_return_val_if_fail(pSB && pWB, false);
140 
141 		if(bReverse)
142 		{
143 			UT_UCS4_strncpy(pSB, RI.m_pChars, RI.m_iLength);
144 			UT_UCS4_strncpy(pSB + RI.m_iLength, m_pChars, m_iLength);
145 
146 			UT_UCS4_strncpy((UT_UCS4Char*)pWB, (UT_UCS4Char*)RI.m_pWidths, RI.m_iLength);
147 			UT_UCS4_strncpy((UT_UCS4Char*)pWB + RI.m_iLength, (UT_UCS4Char*)m_pWidths, m_iLength);
148 		}
149 		else
150 		{
151 			UT_UCS4_strncpy(pSB,m_pChars, m_iLength);
152 			UT_UCS4_strncpy(pSB + m_iLength, RI.m_pChars, RI.m_iLength);
153 
154 			UT_UCS4_strncpy((UT_UCS4Char*)pWB,(UT_UCS4Char*)m_pWidths, m_iLength);
155 			UT_UCS4_strncpy((UT_UCS4Char*)pWB + m_iLength, (UT_UCS4Char*)RI.m_pWidths, RI.m_iLength);
156 		}
157 
158 		*(pSB + m_iLength + RI.m_iLength) = 0;
159 		delete [] m_pChars;
160 		delete [] m_pWidths;
161 
162 		m_pChars = pSB;
163 		m_pWidths = pWB;
164 	}
165 	else
166 	{
167 		UT_DEBUGMSG(("mergeWithNext: reusing existin span buffer\n"));
168 		if(bReverse)
169 		{
170 			// can only shift the text directly in the existing buffer if
171 			// getLength() <= pNext->getLength()
172 			UT_return_val_if_fail(m_iLength <= RI.m_iLength, false);
173 			UT_UCS4_strncpy(m_pChars + RI.m_iLength, m_pChars, m_iLength);
174 			UT_UCS4_strncpy(m_pChars, RI.m_pChars, RI.m_iLength);
175 
176 			UT_UCS4_strncpy((UT_UCS4Char*)m_pWidths + RI.m_iLength,
177 							(UT_UCS4Char*)m_pWidths, m_iLength);
178 
179 			UT_UCS4_strncpy((UT_UCS4Char*)m_pWidths,
180 							(UT_UCS4Char*)RI.m_pWidths, RI.m_iLength);
181 		}
182 		else
183 		{
184 			UT_UCS4_strncpy(m_pChars + m_iLength, RI.m_pChars, RI.m_iLength);
185 
186 			UT_UCS4_strncpy((UT_UCS4Char*)m_pWidths + m_iLength,
187 							(UT_UCS4Char*)RI.m_pWidths, RI.m_iLength);
188 		}
189 		*(m_pChars + m_iLength + RI.m_iLength) = 0;
190 	}
191 
192 	if( RI.m_iJustificationPoints
193 		|| m_iJustificationPoints)
194 	{
195 		// the text is justified, merge the justification information
196 		if(m_iSpaceWidthBeforeJustification == 0xfffffff) // note one less 'f'
197 			m_iSpaceWidthBeforeJustification = RI.m_iSpaceWidthBeforeJustification;
198 
199 		m_iJustificationPoints += ri.m_iJustificationPoints;
200 		m_iJustificationAmount += ri.m_iJustificationAmount;
201 	}
202 
203 	// mark static buffers dirty if needed
204 	if(s_pOwner == this)
205 		s_pOwner = NULL;
206 
207 	m_bLastOnLine = RI.m_bLastOnLine;
208 	m_iTotalLength = m_iTotalLength + RI.m_iTotalLength;
209 	return true;
210 }
211 
212 /*!
213     creates a new instance of GR_*RenderInfo and splits data between
214     ourselves and it at offset
215 
216     bReverse == true indicates data in RTL order
217 
218     we also calculate justification info for the two parts
219 */
split(GR_RenderInfo * & pri,bool bReverse)220 bool  GR_XPRenderInfo::split (GR_RenderInfo *&pri, bool bReverse)
221 {
222 	UT_ASSERT( !pri );
223 	pri = new GR_XPRenderInfo(m_eScriptType);
224 	UT_return_val_if_fail(pri, false);
225 
226 	pri->m_pItem = m_pItem->makeCopy();
227 	UT_return_val_if_fail(pri->m_pItem,false);
228 
229 	GR_XPRenderInfo * pRI = (GR_XPRenderInfo *)pri;
230 
231 	UT_uint32 iPart2Len = m_iLength - m_iOffset;
232 	UT_uint32 iPart1Len = m_iLength - iPart2Len;
233 
234 	m_iLength = iPart1Len;
235 	m_iTotalLength = iPart1Len;
236 
237 	pRI->m_iLength = iPart2Len;
238 	pRI->m_iTotalLength = iPart2Len;
239 
240 	// the question is whether we want to shrink the buffer here (and
241 	// save memory) or leave it too big (and save time); go for memory
242 	// for now
243 	UT_UCS4Char * pSB = new UT_UCS4Char[m_iLength + 1];
244 	UT_sint32   * pWB = new UT_sint32[m_iLength + 1];
245 
246 	UT_return_val_if_fail(pSB && pWB, false);
247 
248 	m_iBufferSize = iPart1Len;
249 
250 	pRI->m_pChars = new UT_UCS4Char[iPart2Len + 1];
251 	pRI->m_pWidths = new UT_sint32[iPart2Len + 1];
252 
253 	UT_return_val_if_fail(pRI->m_pChars && pRI->m_pWidths, false);
254 	pRI->m_iBufferSize = iPart2Len;
255 
256 
257 	if(bReverse)
258 	{
259 		UT_UCS4_strncpy(pSB, m_pChars + pRI->m_iLength, m_iLength);
260 		UT_UCS4_strncpy(pRI->m_pChars, m_pChars, pRI->m_iLength);
261 
262 		UT_UCS4_strncpy((UT_UCS4Char*)pWB, (UT_UCS4Char*)m_pWidths + pRI->m_iLength, m_iLength);
263 		UT_UCS4_strncpy((UT_UCS4Char*)pRI->m_pWidths,
264 						(UT_UCS4Char*)m_pWidths, pRI->m_iLength);
265 	}
266 	else
267 	{
268 		UT_UCS4_strncpy(pSB, m_pChars, m_iLength);
269 		UT_UCS4_strncpy(pRI->m_pChars, m_pChars + m_iLength, pRI->m_iLength);
270 
271 		UT_UCS4_strncpy((UT_UCS4Char*)pWB,(UT_UCS4Char*)m_pWidths, m_iLength);
272 		UT_UCS4_strncpy((UT_UCS4Char*)pRI->m_pWidths,
273 						(UT_UCS4Char*)m_pWidths + m_iLength, pRI->m_iLength);
274 	}
275 
276 	pSB[m_iLength] = 0;
277 
278 	pRI->m_pChars[pRI->m_iLength] = 0;
279 
280 	delete[] m_pChars;
281 	m_pChars = pSB;
282 
283 	delete[] m_pWidths;
284 	m_pWidths = pWB;
285 
286 	pRI->m_eShapingResult = m_eShapingResult;
287 
288 	// Deal with justification
289 	// this has to be always done (used by isJustified())
290 	pRI->m_iSpaceWidthBeforeJustification = m_iSpaceWidthBeforeJustification;
291 
292 	pRI->m_bLastOnLine = m_bLastOnLine;
293 	m_bLastOnLine = false;
294 
295 	if(!isJustified())
296 	{
297 		// we are done
298 		return true;
299 	}
300 
301 
302 	UT_return_val_if_fail(m_pGraphics, false);
303 	pRI->m_pGraphics = m_pGraphics;
304 
305 	UT_sint32 iPoints = m_pGraphics->countJustificationPoints(*pRI);
306 	pRI->m_iJustificationPoints = abs(iPoints);
307 
308 	if(!iPoints)
309 	{
310 		// the latter section has no justification points, all stays
311 		// as is
312 		pRI->m_iJustificationAmount = 0;
313 		return true;
314 	}
315 
316 	iPoints = m_pGraphics->countJustificationPoints(*this);
317 
318 	if(!iPoints)
319 	{
320 		// all justification is done in the latter section
321 		pRI->m_iJustificationAmount = m_iJustificationAmount;
322 		pRI->m_iJustificationPoints = m_iJustificationPoints;
323 
324 		m_iJustificationAmount = 0;
325 		m_iJustificationPoints = 0;
326 
327 		return true;
328 	}
329 
330 	// work out how much of the original amount falls on the new pRI
331 	UT_return_val_if_fail(m_iJustificationPoints, false);
332 	UT_sint32 iAmount = m_iJustificationAmount * pRI->m_iJustificationPoints / m_iJustificationPoints;
333 	pRI->m_iJustificationAmount = iAmount;
334 
335 	m_iJustificationAmount -= iAmount;
336 	m_iJustificationPoints = abs(iPoints);
337 
338 	return true;
339 }
340 
341 /**
342    remove section of length iLen starting at offset from any chaches ...
343    return value false indicates that simple removal was not possible
344    and the caller needs to re-shape.
345 */
cut(UT_uint32 offset,UT_uint32 iLen,bool)346 bool GR_XPRenderInfo::cut(UT_uint32 offset, UT_uint32 iLen, bool /*bReverse*/)
347 {
348 	UT_return_val_if_fail(m_pText, false);
349 	// ascertain the state of the buffer and our shaping requirenments ...
350 	bool bRefresh = (((UT_uint32)m_eState & (UT_uint32)m_eShapingResult ) != 0);
351 	UT_sint32 ioffset = static_cast<UT_sint32>(offset);
352 	UT_sint32 jLen = static_cast<UT_sint32>(iLen);
353 
354 	if(bRefresh)
355 		return false;
356 
357 	m_iTotalLength -= jLen;
358 
359 	// if we got here, we just need to cut out a bit of the draw
360 	// buffer
361 	UT_sint32 iLenToCopy = m_iLength - ioffset - jLen;
362 
363 	if(m_iVisDir == UT_BIDI_RTL)
364 	{
365 		// if this is an rtl run, the end of the draw buffer corresponds to the start
366 		// section of the run, so we are moving not what is left after the deletion,
367 		// but what preceeds it
368 		iLenToCopy = ioffset;
369 	}
370 
371 	UT_return_val_if_fail(iLenToCopy >= 0, false);
372 	if(iLenToCopy)
373 	{
374 		UT_UCS4Char * d = m_pChars+ioffset;
375 		UT_UCS4Char * s = m_pChars+ioffset+jLen;
376 
377 		if(m_iVisDir == UT_BIDI_RTL)
378 		{
379 			d = m_pChars + (m_iLength - (ioffset + jLen));
380 			s = m_pChars + (m_iLength - ioffset);
381 		}
382 
383 		UT_UCS4_strncpy(d, s, iLenToCopy);
384 		m_pChars[m_iLength - iLen] = 0;
385 
386 		d = (UT_UCS4Char *) m_pWidths+ioffset;
387 		s = (UT_UCS4Char *) m_pWidths+ioffset+jLen;
388 
389 		if(m_iVisDir == UT_BIDI_RTL)
390 		{
391 			d = (UT_UCS4Char *) m_pWidths + (m_iLength - (ioffset + jLen));
392 			s = (UT_UCS4Char *) m_pWidths + (m_iLength - ioffset);
393 		}
394 
395 		UT_UCS4_strncpy(d, s, iLenToCopy);
396 		m_pWidths[m_iLength - jLen] = 0;
397 	}
398 
399 	// mark static buffers dirty if needed
400 	if(s_pOwner == this)
401 		s_pOwner = NULL;
402 
403 	return true;
404 }
405 
prepareToRenderChars()406 void GR_XPRenderInfo::prepareToRenderChars()
407 {
408 	if(s_pOwner == this)
409 	{
410 		// we currently own the static buffers, so we do not need to
411 		// do anything
412 		return;
413 	}
414 
415 	// make sure that the static buffers where we temporarily store
416 	// information are big enough
417 	UT_return_if_fail(_checkAndFixStaticBuffers());
418 
419 	// strip placeholders and adjust segment offsets accordingly
420 	_stripLigaturePlaceHolders();
421 
422 	// calculate advances from the pre-processed buffer
423 	_calculateCharAdvances();
424 
425 	s_pOwner = this;
426 }
427 
428 /*!
429     This function no longer does any ligature handling (use the Pango
430 	graphics for that);
431     It still does some preprocessing on the static buffers that is needed by
432     _calculateCharacterAdvances.
433 */
_stripLigaturePlaceHolders()434 void GR_XPRenderInfo::_stripLigaturePlaceHolders()
435 {
436 	UT_return_if_fail(m_iLength <= m_iBufferSize && m_pText);
437 	if(!m_pSegmentOffset)
438 		m_iSegmentCount = 0;
439 
440 	// this is sligthly complicated by having to deal with both
441 	// logical and visual coordinances at the same time
442 	//
443 	// i and j work in visual coordiances, and correspond to the
444 	// orignal pChars array and the s_pCharBuffer
445 	//
446 	// m and iSplitOffset are in logical coordinaces, m being index
447 	// into pWidths, and iSplitOffset a value comparable to pOffset
448 	// values (also in logical order)
449 	UT_sint32 len = (UT_sint32) m_iLength;
450 	bool bReverse = false;
451 
452 	if(m_iVisDir == UT_BIDI_RTL)
453 	{
454 		// we will be using addition on the width buffer so we need to
455 		// zerow it
456 		memset(s_pWidthBuff, 0, sizeof(UT_sint32)*m_iBufferSize);
457 		bReverse = true;
458 	}
459 
460 	for(UT_sint32 i = 0, j = 0; i < len; i++, j++)
461 	{
462 			// ordinary character, just copy it and set the width as
463 			// appropriate
464 			s_pCharBuff[j] = m_pChars[i];
465 
466 			if(bReverse)
467 				s_pWidthBuff[j] += m_pWidths[i];
468 			else
469 				s_pWidthBuff[j] = m_pWidths[i];
470 	}
471 }
472 
473 /**
474    The following code calculates the advances for individual
475    characters that are to be fed to gr_Graphics::drawChars()
476    Note, that character advances are not necessarily identical to
477    character widths; in the case of combining characters the
478    required advance depends on the width of the base character and
479    the properties of the combining character, and it can be both
480    positive and negative.
481 
482    At the moment, we calculate the advances here puting them into
483    a static array. Should this prove to be too much of a
484    performance bottleneck, we could cache this in a member array,
485    and refresh it inside refreshDrawBuffer()
486 */
_calculateCharAdvances()487 void GR_XPRenderInfo::_calculateCharAdvances()
488 {
489 	if(m_iLength == 0)
490 		return;
491 
492 	UT_return_if_fail(m_iLength <= m_iBufferSize);
493 
494 	if(m_iVisDir == UT_BIDI_RTL )
495 	{
496 		// we expect the width array to be the result of processing by
497 		// _stripLigaturePlaceHolders(), which is in the same order as
498 		// the string to which it relates
499 
500 		for(UT_sint32 n = 0; n < m_iLength; n++)
501 		{
502 			if(s_pWidthBuff[n] < 0 || s_pWidthBuff[n] >= GR_OC_LEFT_FLUSHED)
503 			{
504 				UT_sint32 iCumAdvance = 0;
505 
506 				UT_sint32 m = n+1;
507 				while(m < (UT_sint32)m_iLength && s_pWidthBuff[m] < 0)
508 					m++;
509 
510 				if(m >= m_iLength)
511 				{
512 					// problem: this run does not contain the
513 					// character over which we are meant to be
514 					// overimposing our overstriking chars
515 					// we will have to set the offsets to 0
516 					for(UT_sint32 k = n; k < m_iLength; k++)
517 						s_pAdvances[k] = 0;
518 
519 					n = m_iLength;
520 				}
521 				else
522 				{
523 					UT_sint32 k;
524 					for(k = n; k < m; k++)
525 					{
526 						UT_sint32 iAdv;
527 						if(s_pWidthBuff[k] >= GR_OC_LEFT_FLUSHED)
528 						{
529 							UT_sint32 iThisWidth = s_pWidthBuff[k] & GR_OC_MAX_WIDTH;
530 							iAdv = s_pWidthBuff[m] - iThisWidth - iCumAdvance;
531 						}
532 						else
533 						{
534 							// centered character
535 							iAdv = (s_pWidthBuff[m] + s_pWidthBuff[k])/2 - iCumAdvance;
536 						}
537 
538 						if(k == 0)
539 						{
540 							// k == 0, this is the leftmost character,
541 							// so we have no advance to set, but we
542 							// can adjust the starting point of the drawing
543 							m_xoff += iAdv;
544 						}
545 						else if(k == n)
546 						{
547 							// this is a special case; we have already
548 							// calculated the advance in previous
549 							// round of the main loop, and this is
550 							// only adjustment
551 							s_pAdvances[k-1] += iAdv;
552 						}
553 						else
554 							s_pAdvances[k-1] = iAdv;
555 
556 						iCumAdvance += iAdv;
557 					}
558 
559 					s_pAdvances[k-1] = -iCumAdvance;
560 					s_pAdvances[k]   = s_pWidthBuff[m];
561 					n = k; // should be k+1, but there will be n++ in
562 					       // the for loop
563 				}
564 
565 			}
566 			else
567 			{
568 				s_pAdvances[n] = s_pWidthBuff[n];
569 			}
570 		}
571 	}
572 	else
573 	{
574 		for(UT_sint32 n = 0; n < m_iLength; n++)
575 		{
576 			if((n < m_iLength - 1) && ((s_pWidthBuff[n+1] < 0) || (s_pWidthBuff[n+1] >= GR_OC_LEFT_FLUSHED)))
577 			{
578 				// remember the width of the non-zero character
579 				UT_sint32 iWidth = s_pWidthBuff[n];
580 				UT_sint32 iCumAdvance = 0;
581 
582 				// find the next non-zerow char
583 				UT_sint32 m  = n + 1;
584 				while(m < m_iLength && s_pWidthBuff[m] < 0)
585 				{
586 					// plus because pCharWidths[m] < 0
587 					// -1 because it is between m-1 and m
588 					UT_sint32 iAdv;
589 					if(s_pWidthBuff[m] >= GR_OC_LEFT_FLUSHED)
590 					{
591 						UT_sint32 iThisWidth = s_pWidthBuff[m] & GR_OC_MAX_WIDTH;
592 						iThisWidth -= iWidth;
593 
594 						iAdv = -(iThisWidth - iCumAdvance);
595 					}
596 					else
597 					{
598 						//centered character
599 						iAdv = iWidth - (iWidth + s_pWidthBuff[m])/2 + iCumAdvance;
600 					}
601 
602 					s_pAdvances[m-1] = iAdv;
603 					iCumAdvance += iAdv;
604 					m++;
605 				}
606 
607 				n = m-1; // this is the last 0-width char
608 				s_pAdvances[n] = iWidth - iCumAdvance;
609 			}
610 			else
611 				s_pAdvances[n] = s_pWidthBuff[n];
612 			xxx_UT_DEBUGMSG(("%d ",s_pAdvances[n],s_pWidthBuff[n] ));
613 		}
614 		xxx_UT_DEBUGMSG(("ENDRUN \n"));
615 
616 	}
617 }
618 
_checkAndFixStaticBuffers()619 bool GR_XPRenderInfo::_checkAndFixStaticBuffers()
620 {
621 	// TODO -- FIX ME !!!
622 	if(m_iLength > s_iBuffSize)
623 	{
624 		delete [] s_pCharBuff;
625 		s_pCharBuff = new UT_UCS4Char [m_iLength];
626 		UT_return_val_if_fail(s_pCharBuff, false);
627 
628 		delete [] s_pWidthBuff;
629 		s_pWidthBuff = new UT_sint32 [m_iLength];
630 		UT_return_val_if_fail(s_pWidthBuff,false);
631 
632 		delete [] s_pAdvances;
633 		s_pAdvances = new UT_sint32 [m_iLength];
634 		UT_return_val_if_fail(s_pAdvances,false);
635 
636 		s_iBuffSize = m_iLength;
637 	}
638 
639 	return true;
640 }
641 
642 
643