os/textandloc/textrendering/textformatting/test/src/TTmSource.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2 * Copyright (c) 2002-2010 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     4 * This component and the accompanying materials are made available
     5 * under the terms of "Eclipse Public License v1.0"
     6 * which accompanies this distribution, and is available
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     8 *
     9 * Initial Contributors:
    10 * Nokia Corporation - initial contribution.
    11 *
    12 * Contributors:
    13 *
    14 * Description: 
    15 * Test code for MTmSource functionality
    16 *
    17 */
    18 
    19 
    20 #include "TAGMA.H"
    21 #include <e32test.h>
    22 
    23 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
    24 #include "TAGMA_INTERNAL.H"
    25 #endif
    26 
    27 #include "ttmsource.h"
    28 
    29 
    30 #define UNUSED_VAR(a) a = a
    31 
    32 namespace LocalToTTmSource
    33 {
    34 CTTmSourceStep* TestStep = NULL;
    35 #define TESTPOINT(p) TestStep->testpoint(p,(TText8*)__FILE__,__LINE__)
    36 #define TESTPRINT(p) TestStep->print(p,(TText8*)__FILE__,__LINE__)
    37 }
    38 using namespace LocalToTTmSource;
    39 
    40 class TTestGraphicsDeviceMap : public MGraphicsDeviceMap
    41 	{
    42 public:
    43 	TInt HorizontalTwipsToPixels(TInt a) const { return a; }
    44 	TInt VerticalTwipsToPixels(TInt a) const { return a; }
    45 	TInt HorizontalPixelsToTwips(TInt a) const { return a; }
    46 	TInt VerticalPixelsToTwips(TInt a) const { return a; }
    47 	TInt GetNearestFontInTwips(CFont*&,const TFontSpec&)
    48 		{
    49 		return KErrGeneral;
    50 		}
    51 	void ReleaseFont(CFont*) {}
    52 	};
    53 
    54 class CTestPicture : public CPicture
    55 	{
    56 public:
    57 	CTestPicture() {}
    58 	virtual void Draw(CGraphicsContext&, const TPoint&, const TRect&, MGraphicsDeviceMap*) const {}
    59 	virtual void ExternalizeL(RWriteStream&) const {}
    60 	virtual void GetOriginalSizeInTwips(TSize&) const {}
    61 	virtual TBool LineBreakPossible(TUint aClass,TBool aBeforePicture,TBool aHaveSpaces) const
    62 		{
    63 		++iRequestCount;
    64 		if (aBeforePicture)
    65 			{
    66             TESTPOINT(aClass == iClassBefore);
    67             TESTPOINT(aHaveSpaces == iSpacesBefore);
    68 			return iResultBefore;
    69 			}
    70 		TESTPOINT(aClass == iClassAfter);
    71 		TESTPOINT(aHaveSpaces == iSpacesAfter);
    72 		return iResultAfter;
    73 		}
    74 	// expected parameters for LineBreakPossible
    75 	TUint iClassBefore;
    76 	TUint iClassAfter;
    77 	TBool iSpacesBefore;
    78 	TBool iSpacesAfter;
    79 	// Results for breaking before/breaking after
    80 	TBool iResultBefore;
    81 	TBool iResultAfter;
    82 	mutable TInt iRequestCount;
    83 	};
    84 
    85 class TTestSource : public MTmSource
    86 	{
    87 public:
    88 	TTestSource() : iPicturePos(-1) {}
    89 	virtual ~TTestSource() {}
    90 	MGraphicsDeviceMap& FormatDevice() const { return iGDM; }
    91 	MGraphicsDeviceMap& InterpretDevice() const { return iGDM; }
    92 	TInt DocumentLength() const
    93 		{
    94 		return iText->Length();
    95 		}
    96 	void GetText(TInt aPos,TPtrC& aText, TTmCharFormat& aFormat) const
    97 		{
    98 		TTmCharFormat f;
    99 		aFormat = f;
   100 		aText.Set(iText->Mid(aPos));
   101 		}
   102 	void GetParagraphFormatL(TInt, RTmParFormat& aFormat) const
   103 		{
   104 		RTmParFormat p;
   105 		aFormat.CopyL(p);
   106 		}
   107 	CPicture* PictureL(TInt aPos) const
   108 		{
   109 		return aPos == iPicturePos? iPicture : 0;
   110 		}
   111 	TInt ParagraphStart(TInt) const { return 0; }
   112 
   113 	virtual TUint LineBreakClass(TUint aCode, TUint& aRangeStart,
   114 		TUint& aRangeEnd) const
   115 		{
   116 		if ('@' == aCode)
   117 			{
   118 			aRangeStart = aRangeEnd = aCode;
   119 			return ESaLineBreakClass;
   120 			}
   121 		if ('0' <= aCode && aCode <= '9')
   122 			{
   123 			aRangeStart = aRangeEnd = aCode;
   124 			return ELineBreakClasses + aCode - '0';
   125 			}
   126 		return MTmSource::LineBreakClass(aCode, aRangeStart, aRangeEnd);
   127 		}
   128 
   129 	virtual TBool LineBreakPossible(TUint aPrevClass, TUint aNextClass,
   130 		TBool aHaveSpaces) const
   131 		{
   132 		TInt first = static_cast<TInt>(aPrevClass);
   133 		TInt second = static_cast<TInt>(aNextClass);
   134 		TInt customCount = 0;
   135 		if (iDirection < 0)
   136 			{
   137 			first = aNextClass;
   138 			second = aPrevClass;
   139 			}
   140 		if (ELineBreakClasses <= first && first < ELineBreakClasses + 10)
   141 			{
   142 			++customCount;
   143 			TESTPOINT(first - ELineBreakClasses + '0' == FindNextCustomClass());
   144 			TInt countSpaces = CountSpaces();
   145 			TESTPOINT(!aHaveSpaces == !countSpaces);
   146 			}
   147 		if (ELineBreakClasses <= second && second < ELineBreakClasses + 10)
   148 			{
   149 			++customCount;
   150 			TInt c = FindNextCustomClass();
   151 			TESTPOINT(second - ELineBreakClasses + '0' == c);
   152 			}
   153 		if (0 == customCount)
   154 			return MTmSource::LineBreakPossible(aPrevClass, aNextClass, aHaveSpaces);
   155 		// Between custom and non-custom classes, allow a break only with spaces
   156 		// or between @ and 5
   157 		if (1 == customCount)
   158 			return aHaveSpaces
   159 				|| (first == ESaLineBreakClass && second == ELineBreakClasses + 5)
   160 				|| (second == ESaLineBreakClass && first == ELineBreakClasses + 5);
   161 		// Allow a break with spaces except after '0' or before '9'
   162 		if (aHaveSpaces)
   163 			return aPrevClass != ELineBreakClasses && aNextClass != ELineBreakClasses + 9;
   164 		// Allow a break only between a class and the class one more than it.
   165 		return aPrevClass + 1 == aNextClass;
   166 		}
   167 
   168 	virtual TBool GetLineBreakInContext(
   169 		const TDesC& aText, TInt aMinBreakPos, TInt aMaxBreakPos,
   170 		TBool aForwards,TInt& aBreakPos) const
   171 		{
   172 	    TESTPOINT (iDirection == (aForwards? 1 : -1));
   173 		// The allowable break-points should not include the first
   174 		// and last characters of the run.
   175 	    TESTPOINT (aMinBreakPos != 0);
   176 		for (TInt i = aMinBreakPos - 1; i <= aMaxBreakPos; ++i)
   177 		    TESTPOINT('@' == aText[i]);
   178 		++iSaRequestCount;
   179 		aBreakPos = iText->Ptr() + iSaBreakpoint - aText.Ptr();
   180 		return aMinBreakPos <= aBreakPos && aBreakPos <= aMaxBreakPos;
   181 		}
   182 
   183 	virtual TBool IsHangingCharacter(TUint aChar) const
   184 		{
   185 		++iHangingCharRequestCount;
   186 		TESTPOINT(aChar == (*iText)[iMaxBreakPos]);
   187 		if (!iHangingChar)
   188 			return EFalse;
   189 		if (iDirection < 0)
   190 			++iCurrentPos;
   191 		return ETrue;
   192 		}
   193 
   194 	// non-virtual
   195 	TBool GetLineBreakL(const TDesC& aText, TInt aDocPos,
   196 		TInt aMinBreakPos, TInt aMaxBreakPos, TBool aForwards,
   197 		TInt& aBreakPos, TInt& aHangingChars, TInt& aBreakPosAfterSpaces) const
   198 		{
   199 		iText = &aText;
   200 		iMaxBreakPos = aMaxBreakPos;
   201 		iMinBreakPos = aMinBreakPos;
   202 		iHangingCharRequestCount = 0;
   203 		iSaRequestCount = 0;
   204 		iDirection = aForwards? 1 : -1;
   205 		iCurrentPos = aForwards? aMinBreakPos : aMaxBreakPos - 1;
   206 		TBool r = MTmSource::GetLineBreakL(aText, aDocPos,
   207 			aMinBreakPos, aMaxBreakPos, aForwards,
   208 			aBreakPos, aHangingChars, aBreakPosAfterSpaces);
   209 		if (r)
   210 			{
   211             TESTPOINT(aMinBreakPos <= aBreakPos);
   212             TESTPOINT(0 < aBreakPos);
   213             TESTPOINT(aBreakPos <= aHangingChars);
   214             TESTPOINT(aHangingChars <= aBreakPosAfterSpaces);
   215             TESTPOINT(aBreakPos <= aMaxBreakPos);
   216             TESTPOINT(aHangingChars == aBreakPos || iHangingChar);
   217 			// If the direction was backwards, the algorithm should have
   218 			// checked if a hanging character was allowed.
   219 			// This condition could be relaxed to allow it not to be checked
   220 			// if there is no break allowed between the possible hanging
   221 			// character and the previous character.
   222             TESTPOINT(!aForwards || aText.Length() == aMaxBreakPos
   223 				|| 0 < iHangingCharRequestCount);
   224 			// If the maximum break point was chosen or exceeded, the algorithm
   225 			// should have checked to find out whether a hanging character is
   226 			// allowed.
   227             TESTPOINT(aHangingChars < aMaxBreakPos
   228 				|| 0 < iHangingCharRequestCount);
   229 			// Check that only spaces exist between aHangingChars and
   230 			// aMaxBreakPos
   231 			for (TInt i = aHangingChars; i != aBreakPosAfterSpaces; ++i)
   232 				{
   233 				TUint n;
   234 				TESTPOINT(ESpLineBreakClass == LineBreakClass(aText[i], n, n));
   235 				}
   236 			// Check that all the spaces were counted
   237 			TESTPOINT(aBreakPosAfterSpaces == aText.Length()
   238 				|| aText[aBreakPosAfterSpaces] != ' ');
   239 			}
   240 		// Find out how many runs of two or more Sa there are, and check that
   241 		// this matches the number of times that it was requested.
   242 		TInt minChecked = aMinBreakPos - 1;
   243 		TInt maxChecked = aMaxBreakPos + 2;
   244 		if (r)
   245 			{
   246 			if (aForwards)
   247 				maxChecked = aBreakPos + 1;
   248 			else
   249 				minChecked = aBreakPos - 1;
   250 			}
   251 		if (minChecked < 0)
   252 			minChecked = 0;
   253 		if (aText.Length() < maxChecked)
   254 			maxChecked = aText.Length();
   255 		TInt runs = 0;
   256 		TInt sasSoFar = 0;
   257 		TESTPOINT (maxChecked - minChecked < 2
   258 			|| aText[minChecked] != '@'
   259 			|| aText[minChecked + 1] != '@'
   260 			|| !aForwards
   261 			|| aHangingChars == iSaBreakpoint);
   262 		for (; minChecked != maxChecked; ++minChecked)
   263 			{
   264 			if (aText[minChecked] == '@')
   265 				++sasSoFar;
   266 			else
   267 				{
   268 				if (1 < sasSoFar)
   269 					++runs;
   270 				sasSoFar = 0;
   271 				}
   272 			}
   273 		if (1 < sasSoFar)
   274 			++runs;
   275 		TESTPOINT(sasSoFar < 2 || aForwards || aHangingChars == iSaBreakpoint);
   276 		TESTPOINT(runs == iSaRequestCount);
   277 		return r;
   278 		}
   279 
   280 	TInt FindNextCustomClass() const
   281 		{
   282 		TInt end = iDirection < 0? -1 : iText->Length();
   283 		for (; iCurrentPos != end; iCurrentPos += iDirection)
   284 			{
   285 			TInt c = (*iText)[iCurrentPos];
   286 			if ('0' <= c && c <= '9')
   287 				return c;
   288 			}
   289 		return -1;
   290 		}
   291 	TInt CountSpaces() const
   292 		{
   293 		TInt end = iDirection < 0? -1 : iText->Length();
   294 		TInt count = 0;
   295 		if (iCurrentPos == end)
   296 			return 0;
   297 		iCurrentPos += iDirection;
   298 		for (; iCurrentPos != end; iCurrentPos += iDirection, ++count)
   299 			{
   300 			TInt c = (*iText)[iCurrentPos];
   301 			if (' ' != c)
   302 				return count;
   303 			}
   304 		return count;
   305 		}
   306 
   307 private:
   308 	mutable TTestGraphicsDeviceMap iGDM;
   309 	mutable const TDesC* iText;
   310 	mutable TInt iMaxBreakPos;
   311 	mutable TInt iMinBreakPos;
   312 
   313 	mutable TInt iDirection;
   314 	mutable TInt iCurrentPos;
   315 	mutable TInt iHangingCharRequestCount;
   316 	mutable TInt iSaRequestCount;
   317 
   318 public:
   319 	TInt iPicturePos;
   320 	CPicture* iPicture;
   321 
   322 	TBool iHangingChar;
   323 
   324 	TInt iSaBreakpoint;
   325 	};
   326 
   327 TInt TestLineBreak(const TDesC& aText, TInt aSaBreak, TBool aHangingChar,
   328 	TInt aMin, TInt aMax, TBool aForwards)
   329 	{
   330 	if (aMax == 0)
   331 		aMax = aText.Length();
   332 	TTestSource t;
   333 	t.iHangingChar = aHangingChar;
   334 	t.iSaBreakpoint = aSaBreak;
   335 	TInt b0, b1, b2;
   336 	b0 = KMaxTInt;
   337 	b1 = KMaxTInt;
   338 	b2 = KMaxTInt;
   339 	return t.GetLineBreakL(aText, 0, aMin, aMax, aForwards, b0, b1, b2)?
   340 		b1 : -1;
   341 	}
   342 
   343 CTTmSourceStep::CTTmSourceStep()
   344     {
   345     
   346     }
   347 
   348 
   349 TVerdict CTTmSourceStep::doTestStepL()
   350 	{
   351     SetTestStepResult(EPass);
   352     TestStep = this;
   353     TESTPRINT(_L("TTmSource - MTmSource tests"));
   354 	TESTPRINT(_L(" @SYMTestCaseID:SYSLIB-FORM-LEGACY-TTMSOURCE-0001 Line-Break Tests: "));
   355 
   356 	TEST(-1 == TestLineBreak(_L(""), 0, 0, 0, 0, 0));
   357 	TEST(-1 == TestLineBreak(_L("5"), 0, 0, 0, 0, 0));
   358 	TEST(-1 == TestLineBreak(_L("5"), 0, 0, 0, 0, 1));
   359 	TEST(-1 == TestLineBreak(_L("@"), 1, 0, 0, 0, 0));
   360 	TEST(1 == TestLineBreak(_L("a   b"), 0, 0, 0, 0, 0));
   361 	TEST(-1 == TestLineBreak(_L("0 0 0 9    9"), 0, 0, 0, 0, 0));
   362 	TEST(-1 == TestLineBreak(_L("0 0 0 9    9"), 0, 0, 0, 0, 1));
   363 	TEST(9 == TestLineBreak(_L("4242454445"), 0, 0, 0, 0, 0));
   364 	TEST(5 == TestLineBreak(_L("4242454445"), 0, 0, 0, 0, 1));
   365 	TEST(5 == TestLineBreak(_L("hello there"), 0, 0, 0, 0, 0));
   366 	TEST(5 == TestLineBreak(_L("hello there"), 0, 0, 0, 0, 1));
   367 	TEST(-1 == TestLineBreak(_L("hel  the re"), 0, 0, 5, 7, 0));
   368 	TEST(-1 == TestLineBreak(_L("hel  the re"), 0, 0, 5, 7, 1));
   369 	TEST(8 == TestLineBreak(_L("hel  the re"), 0, 1, 5, 7, 0));
   370 	TEST(8 == TestLineBreak(_L("hel  the re"), 0, 1, 6, 7, 1));
   371 	TEST(3 == TestLineBreak(_L("@@@@@"), 3, 0, 0, 0, 0));
   372 	TEST(3 == TestLineBreak(_L("@@@@@"), 3, 0, 0, 0, 1));
   373 	TEST(5 == TestLineBreak(_L("9999@@@@@00099@@@@gfra"), 5, 0, 5, 0, 0));
   374 	TEST(5 == TestLineBreak(_L("9999@@@@@00099@@@@gfra"), 5, 0, 5, 0, 1));
   375 	TEST(16 == TestLineBreak(_L("9999@@@@@00099@@@@gfra"), 16, 0, 0, 0, 0));
   376 	TEST(16 == TestLineBreak(_L("9999@@@@@00099@@@@gfra"), 16, 0, 0, 0, 1));
   377 	TEST(5 == TestLineBreak(_L("55@@@55"), 0, 0, 0, 0, 0));
   378 	TEST(2 == TestLineBreak(_L("55@@@55"), 0, 0, 0, 0, 1));
   379 	TEST(3 == TestLineBreak(_L("55@55"), 0, 0, 0, 0, 0));
   380 	TEST(2 == TestLineBreak(_L("55@55"), 0, 0, 0, 0, 1));
   381 
   382 	// Test for DEF046468, which was caused by the TLineBreakIterator constructor accessing past the end of a string
   383 	TESTPRINT(_L("Line-Break DEF046468 Test:"));
   384 	// Create a string of 16 chars with a picture code at the 17th position
   385 	_LIT(KLarsString, "dolor sit amet, \xFFFC");
   386 	// Create a TPtrC for the 16 character string ( with the picture code after the string in memory )
   387 	TBufC<20> KTestBuffer(KLarsString);
   388 	TPtrC KTestString( reinterpret_cast<const TUint16*>(KTestBuffer.Ptr()), 16);
   389 	// Test the iterator overrun. If iterator accesses past the end of the array, it'll get picture code and crash
   390 	TEST(9 == TestLineBreak(KTestString,0,0,1,15,0));
   391 	
   392 	return TestStepResult();
   393 	}