--- a/graphicsdeviceinterface/gdi/sgdi/GlyphSel.cpp Thu Sep 02 21:50:40 2010 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,593 +0,0 @@
-// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
-// All rights reserved.
-// This component and the accompanying materials are made available
-// under the terms of "Eclipse Public License v1.0"
-// which accompanies this distribution, and is available
-// at the URL "http://www.eclipse.org/legal/epl-v10.html".
-//
-// Initial Contributors:
-// Nokia Corporation - initial contribution.
-//
-// Contributors:
-//
-// Description:
-//
-
-/**
- @file
- @internalComponent
-*/
-
-
-#include <gdi.h>
-#include <openfont.h>
-#include "GlyphSel.h"
-#include "GDIPANIC.h"
-
-
-static const TText16 KLatinGlyph_SoftHyphen = 0x00AD;
-
-
-//
-//
-// TUtf32Iterator Class definition
-//
-//
-
-
-TUint TUtf32Iterator::UTF16ToTChar(const TText16* a)
-/**
- This routine takes an encoded UTF16 byte array and decodes the
- first character at the start of the array and returns it as a TChar.
- If the char is "not a char" character 0xFFFF results.
-@param a
- UTF16 byte array to be decoded.
-@param aPr
- Position pointer 'a' derived from, incremented if surragote pairs decoded.
-@return
- The character value in UTF32 format or 0xFFFF it not a character.
-*/
- {
- // Is next char a surrogate?
- if (0xD800 == (a[0] & 0xF800))
- {
- // Is it a high surrogate in the range D800..DBFF?
- if (0xD800 == (a[0] & 0xFC00))
- {
- // Its a high surrogate, is the next char a low surrogate?
- if (0xDC00 == (a[1] & 0xFC00))
- {
- // It's a low surrogate
- return ((a[0] - 0xd7f7) << 10) + a[1];
- }
- else
- return 0xFFFF;
- }
- else
- return 0xFFFF;
- }
- else
- return a[0];
- }
-
-
-TUtf32Iterator::TUtf32Iterator(const TText16* aStart, const TText16* aEnd, TInt aStartingIndex)
-/**
- Construct iterator given UTF16 encoded byte array.
-@param aStart
- Start address of the array.
-@param aEnd
- Address of the byte just beyond the end of the array.
-@param aStartingIndex
- Optional UTF16 offset into the array to initialise the current position to.
-@panic EGdiPanic_InvalidInputParam
- Raised when array start if passed the array end.
-*/
-: iStart(aStart), iCurrent(aStart+aStartingIndex), iEnd(aEnd), iChar(0xffff)
- {
- GDI_ASSERT_DEBUG(iStart < iEnd, EGdiPanic_InvalidInputParam);
-
- if (iCurrent > iEnd)
- iCurrent = iEnd;
- else if (iCurrent < iStart)
- iCurrent = iStart;
- else
- {
- // Sanatise array end checking for an unpaired surrogate value
- // so that UTF16ToTChar() does not read off the end of the array.
- if (0xD800 == (iEnd[-1] & 0xFC00))
- {
- if (iCurrent == iEnd-1)
- ++iCurrent;
- else
- --iEnd;
- }
-
- // Setup initial position UTF32 character value
- iChar = UTF16ToTChar(iCurrent);
- }
- }
-
-
-TChar TUtf32Iterator::Next()
-/**
-Moves the iterator forward to the next valid UTF32 character value.
-@return TChar The next character in the text towards the end.
-@panic EGdiPanic_OutOfText
-Raised when there is no next position to move to.
-*/
- {
- GDI_ASSERT_DEBUG(iCurrent < iEnd, EGdiPanic_OutOfText);
-
- iCurrent += (iChar > 0xffff) ? 2 : 1;
- if (iCurrent < iEnd)
- iChar = UTF16ToTChar(iCurrent);
- else
- iChar = 0xFFFF;
- return iChar;
- }
-
-
-TChar TUtf32Iterator::Prev()
-/**
-Moves the iterator backwards to the next valid UTF32 character value.
-@return TChar The prev character in the text towards the start.
-@panic EGdiPanic_OutOfText Raised when there is no next position to move to.
-*/
- {
- GDI_ASSERT_DEBUG(iCurrent >= iStart, EGdiPanic_OutOfText);
-
- --iCurrent;
- if (iCurrent >= iStart)
- iChar = UTF16ToTChar(iCurrent);
- else
- iChar = 0xFFFF;
- return iChar;
- }
-
-
-void TUtf32Iterator::SetPos(TInt aPos)
-/**
- Moves the iterator to the position specified by array start+offset.
-@param aPos
- UTF16 offset into the array to set the current position to.
-@panic EGdiPanic_OutOfText
- Raised when there is no next position to move to.
-*/
- {
- GDI_ASSERT_DEBUG(iStart+aPos <= iEnd, EGdiPanic_OutOfText);
- GDI_ASSERT_DEBUG(iStart+aPos >= iStart, EGdiPanic_OutOfText);
-
- iCurrent = iStart+aPos;
- iChar = UTF16ToTChar(iCurrent);
- }
-
-
-TUint TUtf32Iterator::Get(TInt offset)
-/**
- Returns the UTF32 char value at the offset specified. 0xFFFF may be returned
- for unpaired surrogate and noncharacters. Does not change the current
- position.
-@param offset
- UTF16 offset from current iterator position to get UTF32 char form.
-@return TChar
- UTF32 char value found at the iterator+offset, or 0xFFFF in error.
-@panic EGdiPanic_OutOfText
- Raised when offset found to be outside the bounds of the original text array.
-*/
- {
- GDI_ASSERT_DEBUG(iCurrent+offset >= iStart, EGdiPanic_OutOfText);
- GDI_ASSERT_DEBUG(iCurrent+offset < iEnd, EGdiPanic_OutOfText);
-
- return UTF16ToTChar(iCurrent+offset);
- }
-
-
-TChar TUtf32Iterator::GetThenNext()
-/**
- Return the UTF32 value at the current position.
-@return TChar
- UTF32 value currently pointed to by iterator.
-@panic EGdiPanic_EndOfText
- Raised when current iterator position is not valid.
-*/
- {
- GDI_ASSERT_DEBUG(iCurrent < iEnd, EGdiPanic_OutOfText);
-
- TChar current(iChar);
- iCurrent += (iChar > 0xffff) ? 2 : 1;
- if (iCurrent < iEnd)
- iChar = UTF16ToTChar(iCurrent);
- else
- iChar = 0xFFFF;
- return current;
- }
-
-
-TChar TUtf32Iterator::GetThenPrev()
-/**
- Return the UTF32 value at the current position.
-@return TChar
- UTF32 value currently pointed to by iterator.
-@panic EGdiPanic_EndOfText
- Raised when current iterator position is not valid.
-*/
- {
- GDI_ASSERT_DEBUG(iCurrent >= iStart, EGdiPanic_OutOfText);
-
- TChar current(iChar);
- --iCurrent;
- if (iCurrent >= iStart)
- iChar = UTF16ToTChar(iCurrent);
- else
- iChar = 0xFFFF;
- return current;
- }
-
-
-TInt TUtf32Iterator::LengthToStart() const
-/**
- Returns the number of TText16 codes between the start point and its
- current position.
-@return TInt
- Number of TText16 characters between array start and current iterator
- position.
-*/
- {
- return iCurrent-iStart;
- }
-
-
-TInt TUtf32Iterator::LengthToEnd() const
-/**
- Returns the number of remaining TText16 codes still ahead of the
- iterator.
-@return TInt
- Number of TText16 characters between array current iterator position
- and the end of the array.
-*/
- {
- return iEnd - iCurrent;
- }
-
-const TText16* TUtf32Iterator::CurrentPosition() const
- {
- return iCurrent;
- }
-
-void TUtf32Iterator::SetCurrentPosition(const TText16* a)
- {
- iCurrent = a;
- }
-
-//
-//
-// TGlyphSelectionState Class definition
-//
-//
-
-
-/**
- The Unicode Combining Class values recognised by the
- GlyphSelUtils::CombineLastGlyphToBase method.
-@internalComponent
-*/
-enum TCombiningClass
- {
- EArabicFathatan = 27,
- EArabicDammatan = 28,
- EArabicKasratan = 29,
- EArabicFatha = 30,
- EArabicDamma = 31,
- EArabicKasra = 32,
- EArabicShadda = 33,
- EArabicSukun = 34,
- ECombineBelowLeftAttached = 200,
- ECombineBelowAttached = 202,
- ECombineBelowRightAttached = 204,
- ECombineLeftAttached = 208,
- ECombineRightAttached = 210,
- ECombineAboveLeftAttached = 212,
- ECombineAboveAttached = 214,
- ECombineAboveRightAttached = 216,
- ECombineBelowLeft = 218,
- ECombineBelow = 220,
- ECombineBelowRight = 222,
- ECombineLeft = 224,
- ECombineRight = 226,
- ECombineAboveLeft = 228,
- ECombineAbove = 230,
- ECombineAboveRight = 232
- };
-
-
-/**
- This method is called to attach (by adjusing its bounding box) the current end
- glyph in the output array of iParam to the base glyph bounding box based on
- the Unicode combining class of the character.
-@param aGss
- The general input/output glyph selection data for the routine.
-@param aGss.iOutput
- Input: Glyph cluster with last glyph an actual combining character. Output:
- Bounding box of last glyph adjusted according to char combining class.
-@param aFirstDiacritic
- Which character in the output array to treat as the first diacritic of the
- cluster. Usually 1, but can be more if the base class is a ligature.
-*/
-void TGlyphSelectionState::CombineLastGlyphToBase(const TRect& aBase, TInt aFirstDiacritic)
- {
- // Get the bounds of all the base characters.
- TRect base = aBase;
- int last = iParam.iOutputGlyphs-1;
- for (int i = aFirstDiacritic; i < last; i++)
- base.BoundingRect(iParam.iOutput[i].iBounds);
-
- // Calculate the attachment points.
- TRect& r = iParam.iOutput[last].iBounds;
- int w = r.Width();
- int h = r.Height();
- int t = r.iTl.iY;
- int l = r.iTl.iX;
- int left = base.iTl.iX;
- int center = base.iTl.iX + (base.Width() - w) / 2;
- int right = base.iBr.iX - w;
- int below = base.iBr.iY;
- int above = base.iTl.iY - h;
- int left_of = left - w;
- int right_of = right + w;
- int xGap = 1;
- int yGap = iFont->HeightInPixels()/10;
-
- // Select attachment based on combining class.
- switch (iCombCls)
- {
- case ECombineBelowLeftAttached:
- t = below;
- l = left;
- break;
- case ECombineBelowAttached:
- t = below;
- l = center;
- break;
- case ECombineBelowRightAttached:
- t = below;
- l = right;
- break;
- case ECombineLeftAttached:
- l = left_of;
- break;
- case ECombineRightAttached:
- l = right_of;
- break;
- case ECombineAboveLeftAttached:
- t = above;
- l = left;
- break;
- case ECombineAboveAttached:
- t = above;
- l = center;
- break;
- case ECombineAboveRightAttached:
- t = above;
- l = right;
- break;
- case ECombineBelowLeft:
- t = below + yGap;
- l = left;
- break;
- case ECombineBelow:
- case EArabicKasratan:
- case EArabicKasra:
- t = below + yGap;
- l = center;
- break;
- case ECombineBelowRight:
- t = below + yGap;
- l = right;
- break;
- case ECombineLeft:
- l = left_of - xGap;
- break;
- case ECombineRight:
- l = right_of + xGap;
- break;
- case ECombineAboveLeft:
- t = above - yGap;
- l = left;
- break;
- case ECombineAbove:
- case EArabicFathatan:
- case EArabicDammatan:
- case EArabicFatha:
- case EArabicDamma:
- case EArabicShadda:
- case EArabicSukun:
- t = above - yGap;
- l = center;
- break;
- case ECombineAboveRight:
- t = above - yGap;
- l = right;
- break;
- default:
- l = center;
- break;
- }
-
- // Adjust the bounding box of the last glyph to fix position
- // based on the characters combining class. For speed, do directly.
- // r.SetRect(l,t,l + w,t + h);
- r.iTl.iX = l;
- r.iTl.iY = t;
- r.iBr.iX = l+w;
- r.iBr.iY = t+h;
- }
-
-
-TBool TGlyphSelectionState::AppendGlyphToCluster(TUint aCode)
-/**
- This common method is used by glyph selector classes to add a glyph to
- the end of the aGss.iParam output field filling in all the glyph info
- needed.
-@param aCode
- The Unicode character for which a glyph should be appended.
-@param aGss
- The general input/output glyph selection data for the routine.
-@return TBool
- ETrue when successful, EFalse when failure occurs e..g no char data, overflow
-*/
- {
- // Setup reference to next free glyph record we need to update.
- GDI_ASSERT_DEBUG(iParam.iOutputGlyphs < CFont::TPositionParam::EMaxOutputGlyphs,
- EGdiPanic_InvalidInputParam);
-
- CFont::TPositionParam::TOutput* output = iParam.iOutput+iParam.iOutputGlyphs;
-
- // Retrieve the glyph details from the Font. Essential to proceed, abort
- // if not available.
- TOpenFontCharMetrics metrics;
- if (iFont->GetCharacterData(aCode, metrics, output->iBitmap,
- output->iBitmapSize) == CFont::ENoCharacterData)
- return EFalse;
-
- // Set code point of glyph in output record.
- output->iCode = aCode;
-
- // Set the glyph's bounds in the output record and record pen advancement.
- if (iParam.iDirection == CFont::EVertical)
- {
- metrics.GetVertBounds(output->iBounds);
- iAdvance.iHeight = Max(iAdvance.iHeight, metrics.VertAdvance());
- }
- else
- {
- metrics.GetHorizBounds(output->iBounds);
- iAdvance.iWidth = Max(iAdvance.iWidth, metrics.HorizAdvance());
- }
-
- // Next adjust the glyph's bounding box to offset it from the pen
- // position (origin of drawing). For speed increment attributes directly.
- // output->iBounds.Move(aGss.iParam.iPen);
- output->iBounds.iTl.iX += iParam.iPen.iX;
- output->iBounds.iBr.iX += iParam.iPen.iX;
- output->iBounds.iTl.iY += iParam.iPen.iY;
- output->iBounds.iBr.iY += iParam.iPen.iY;
-
- // Before we exit with success, increment the glyph array counter.
- // for the new glyph we've added here.
- iParam.iOutputGlyphs++;
- return ETrue;
- }
-
-
-//
-//
-// GlyphSelector_SoftHyphen Class definition
-//
-//
-
-TBool GlyphSelector_SoftHyphen::Process(TGlyphSelectionState& aGss, RShapeInfo&)
-/**
-@see GlyphSelUtils
- See this class for the method description.
-*/
- {
- aGss.iText.Next();
- if (!aGss.iText.AtEnd())
- {
- // Here we skip & don't output hyphen since its not at the end a line.
- aGss.iPen = TGlyphSelectionState::EPenAdvance_No;
- }
- else
- {
- // If we reach here we must output hyphen.
- if (!aGss.AppendGlyphToCluster(KLatinGlyph_SoftHyphen))
- return EFalse;
-
- aGss.iPen = TGlyphSelectionState::EPenAdvance_Yes;
- }
-
- // Logic to determine if we are now at the end of the glyph cluster.
- // Default logic, based on whether a combining mark follows or not.
- aGss.iClusterState =
- (!aGss.iText.AtEnd() &&
- ((aGss.iText.Get().GetCategory() & 0xF0) == TChar::EMarkGroup)) ?
- TGlyphSelectionState::EGClusterNotComplete : TGlyphSelectionState::EGClusterComplete;
-
- return ETrue;
- }
-
-
-//
-//
-// GlyphSelector_Default Class definition
-//
-//
-
-
-TBool GlyphSelector_Default::Process(TGlyphSelectionState& aGss, RShapeInfo&)
-/**
-@see GlyphSelUtils
- See this class for the method description.
-*/
- {
-
- // In this method we always output the glyph.
- if (!aGss.AppendGlyphToCluster(aGss.iText.GetThenNext()))
- return EFalse;
-
- // Adjust glyph's bounds further to position this character if it is a
- // combining mark
- if (aGss.IsCombiningClass())
- {
- aGss.iPen = TGlyphSelectionState::EPenAdvance_No;
-
- TRect baseBounds(aGss.iParam.iOutput[0].iBounds);
- // Get first character in this glyph cluster. In this default process function, the iCode should
- // be Unicode Point Code.
- TChar startChar = TChar(aGss.iParam.iOutput[0].iCode);
- // Character index in the output array to treat as the first diacritic of the
- // cluster. It will be used as first character for combine to. usually 1, but when
- // the cluster starts with a combining mark, it should be set to 0.
- TInt indexOfFirstCombining = 1;
- TInt startCharCat = startChar.GetCategory() & 0xF0;
-
- // if the first character in this cluster is a combining mark or a graphically empty character,
- // (such as a space Character0x0020), a fake bound, formed from the Ascent of the font, will be
- // used for combining
- if ((startCharCat == TChar::EMarkGroup) || baseBounds.Size() == TSize(0,0))
- {
- // Determine the height of the combining glyph.
- TInt glyphHeight = 0;
- if (aGss.iParam.iOutputGlyphs == 1)
- {
- glyphHeight = aGss.iParam.iOutput[0].iBitmapSize.iHeight;
- }
- else
- {
- glyphHeight = aGss.iParam.iOutput[1].iBitmapSize.iHeight;
- }
- // Adjust Y values to a ficticious but reasonable range for it to combine to using the glyph height to adjust correctly below the font ascent.
- baseBounds.iTl.iY = aGss.iParam.iPen.iY - aGss.iFont->AscentInPixels() + glyphHeight; //modest ascender
- baseBounds.iBr.iY = aGss.iParam.iPen.iY; //No descender
- }
-
- if (startCharCat == TChar::EMarkGroup)
- indexOfFirstCombining = 0;
-
- aGss.CombineLastGlyphToBase(baseBounds, indexOfFirstCombining);
- aGss.iGlyphPostCombine = TGlyphSelectionState::EGPostCombine_Yes;
- }
- else
- aGss.iPen = TGlyphSelectionState::EPenAdvance_Yes;
-
- // Logic to determine if we are now at the end of the glyph cluster.
- // Default logic, based on whether a combining mark follows or not.
- aGss.iClusterState =
- (!aGss.iText.AtEnd() &&
- ((aGss.iText.Get().GetCategory() & 0xF0) == TChar::EMarkGroup)) ?
- TGlyphSelectionState::EGClusterNotComplete : TGlyphSelectionState::EGClusterComplete;
-
- return ETrue;
- }
-