sl@0: // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // Contains client-side shaper functionality. sl@0: // sl@0: // sl@0: sl@0: #include "ShapeImpl.h" sl@0: #include "ShapeInfo.h" sl@0: #include sl@0: #include "GDIPANIC.h" sl@0: sl@0: GLREF_C void Panic(TInt aError); sl@0: sl@0: /** Construct an RShapeInfo. */ sl@0: /** @internalComponent */ sl@0: EXPORT_C RShapeInfo::RShapeInfo() sl@0: : iFont(0), iHeader(0), iEndOfShapedText(-1), iContextualProcessFunc(0) {} sl@0: sl@0: /** Perform shaping on the text in aText between aStartOfTextToShape and sl@0: aEndOfTextToShape, based on the script conventions implied by aScriptCode. sl@0: @param aFont The font to use for the shaping. sl@0: @param aText The text, including context. sl@0: @param aStartOfTextToShape sl@0: The start position within aText of the text to be shaped. sl@0: @param aEndOfTextToShape sl@0: The end position within aText of the text to be shaped. sl@0: @param aScriptCode The script code for the script being shaped. sl@0: @param aLanguageCode The language code for the language being shaped. sl@0: @return sl@0: KErrNone if the text was successfully shaped, KErrNotSupported if aFont has sl@0: no shaper, KErrCouldNotConnect if the font bitmap server has not been sl@0: started. sl@0: */ sl@0: TInt RShapeInfo::Open(const CFont* aFont, const TDesC& aText, sl@0: TInt aStartOfTextToShape, TInt aEndOfTextToShape, sl@0: TInt aScriptCode, TInt aLanguageCode) sl@0: { sl@0: GDI_ASSERT_DEBUG(0 <= aStartOfTextToShape, sl@0: EGdiPanic_InvalidInputParam); sl@0: GDI_ASSERT_DEBUG(aStartOfTextToShape <= aEndOfTextToShape, sl@0: EGdiPanic_InvalidInputParam); sl@0: GDI_ASSERT_DEBUG(aEndOfTextToShape <= aText.Length(), sl@0: EGdiPanic_InvalidInputParam); sl@0: iFont = aFont; sl@0: TFontShapeFunctionParameters param; sl@0: param.iText = &aText; sl@0: param.iStart = aStartOfTextToShape; sl@0: param.iEnd = aEndOfTextToShape; sl@0: param.iScript = aScriptCode; sl@0: param.iLanguage = aLanguageCode; sl@0: const TInt r = aFont->ExtendedFunction(KFontGetShaping, ¶m); sl@0: iHeader = r == KErrNone ? param.iShapeHeaderOutput : 0; sl@0: if(iHeader) sl@0: iEndOfShapedText = aEndOfTextToShape; sl@0: return r; sl@0: } sl@0: sl@0: /** Frees the memory associated with this shaping information. */ sl@0: /** @internalComponent */ sl@0: EXPORT_C void RShapeInfo::Close() sl@0: { sl@0: if (iHeader) sl@0: { sl@0: TFontShapeDeleteFunctionParameters param; sl@0: param.iShapeHeader = iHeader; sl@0: iFont->ExtendedFunction(KFontDeleteShaping, ¶m); sl@0: iHeader = NULL; sl@0: iEndOfShapedText = -1; sl@0: // We don't reset iSingleContextChar because we want the context to remain throughout, sl@0: // even when the session is closed. It would eventually simply go out of scope. sl@0: } sl@0: } sl@0: sl@0: /** Returns the number of glyphs in the shaped output. sl@0: @return The number of glyphs. Also equal to the size of the Glyphs() array and sl@0: the GlyphPositions() array. */ sl@0: TInt RShapeInfo::GlyphCount() const sl@0: { sl@0: GDI_ASSERT_ALWAYS(iHeader, EGdiPanic_Invariant); sl@0: return iHeader->iGlyphCount; sl@0: } sl@0: sl@0: /** Returns the array of glyphs. These must be ORed with 0x80000000 to make sl@0: glyph numbers that functions like CFbsFont::Rasterize can accept to avoid sl@0: confusing glyph numbers with Unicode character numbers. sl@0: @return The glyph array. The size of this array is RShapeInfo::GlyphCount sl@0: @see GlyphCount */ sl@0: const TInt32* RShapeInfo::Glyphs() const sl@0: { sl@0: GDI_ASSERT_ALWAYS(iHeader, EGdiPanic_Invariant); sl@0: return reinterpret_cast(iHeader->iBuffer); sl@0: } sl@0: sl@0: /** Returns the array of positions for the glyphs returned by Glyphs, and the sl@0: total advance for the text. sl@0: @return sl@0: Array of glyph positions in pixels, relative to the pen position before sl@0: the glyphs are drawn. The array has GlyphCount() + 1 entries, as the sl@0: last entry represents the total advance of the text. */ sl@0: const RShapeInfo::TPoint16* RShapeInfo::GlyphPositions() const sl@0: { sl@0: GDI_ASSERT_ALWAYS(iHeader, EGdiPanic_Invariant); sl@0: return reinterpret_cast(iHeader->iBuffer sl@0: + ((iHeader->iGlyphCount) << 2)); sl@0: } sl@0: sl@0: /** Returns the pen advance these glyphs require. sl@0: @return The pen advance; where to move the pen after drawing all the glyphs. */ sl@0: RShapeInfo::TPoint16 RShapeInfo::Advance() const sl@0: { sl@0: GDI_ASSERT_ALWAYS(iHeader, EGdiPanic_Invariant); sl@0: RShapeInfo::TPoint16 r; sl@0: r.iX = *reinterpret_cast(iHeader->iBuffer sl@0: + (iHeader->iGlyphCount << 3)); sl@0: r.iY = *reinterpret_cast(iHeader->iBuffer sl@0: + (iHeader->iGlyphCount << 3) + 2); sl@0: return r; sl@0: } sl@0: sl@0: /** Returns the array of indices. sl@0: @return sl@0: Indices[n] is the position in the input text that produced Glyphs[n]. sl@0: */ sl@0: const TInt16* RShapeInfo::Indices() const sl@0: { sl@0: GDI_ASSERT_ALWAYS(iHeader, EGdiPanic_Invariant); sl@0: return reinterpret_cast(iHeader->iBuffer sl@0: + (iHeader->iGlyphCount << 3) + 4); sl@0: } sl@0: sl@0: TInt RShapeInfo::EndOfShapedText() sl@0: { sl@0: return iEndOfShapedText; sl@0: } sl@0: sl@0: /** Checks if this shaping information is still occupying memory. */ sl@0: EXPORT_C TBool RShapeInfo::IsOpen() sl@0: { sl@0: if(iHeader && iHeader->iGlyphCount >= 0 && iHeader->iCharacterCount >=0) sl@0: return ETrue; sl@0: else sl@0: return EFalse; sl@0: sl@0: } sl@0: sl@0: void RShapeInfo::SetContext(TAny* aContextualProcessFunc) sl@0: { sl@0: iContextualProcessFunc = aContextualProcessFunc; sl@0: } sl@0: sl@0: TAny* RShapeInfo::GetContext() sl@0: { sl@0: return iContextualProcessFunc; sl@0: } sl@0: