diff -r 000000000000 -r bde4ae8d615e os/graphics/graphicsdeviceinterface/directgdi/src/directgdicontext.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/graphics/graphicsdeviceinterface/directgdi/src/directgdicontext.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,3588 @@ +// Copyright (c) 2007-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: +// + +#include "directgdicontext.h" +#include "directgdipaniccodes.h" +#include "directgdifont.h" +#include "directgdidriver.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace DirectGdi; + +/** +CDirectGdiContext InternalizeL/ExternalizeL - version numbers. +Add new version numbers here. A reason of adding new version numbers may be adding new +CDirectGdiContext data members, which may have to be externalized/internalized. +When that happens: +1.Put a new enum item (like EDirectGDIContext_Ver01) with a version number, which is greater than +the last version number, that was used. +2.Document the new enum item. +3.Update KDirectGDIContext_VerNo value to be the new enum item value. +4.Update InternalizeL/ExternalizeL methods after adding the new version number. +For example: If a new member is added to the class - TInt iSmth, when InternalizeL +is called to operate on older archive, iSmth member won't be in the archive! +So, in InternalizeL, there should be a check, something like: +TUint16 archiveVerNo = 0; + aReadStream >> archiveVerNo; + if(archiveVerNo < EDirectGDIContext_Ver02) //EDirectGDIContext_Ver02 has been added, when iSmth has been added + { + //Do nothing - iSmth is not in the archive + //Initialize it with some default value + iSmth = KDefVal; + } + else + { + aReadStream >> iSmth; + } +*/ +enum + { + EDirectGDIContext_Ver01 = 1 //Base version number, when InternalizeL/ExternalizeL were added + }; + +LOCAL_D const TUint16 KDirectGDIContext_VerNo = EDirectGDIContext_Ver01; + +/** +Static two-phase factory constuctor. Creates an object of this class. + +@param aDirectGdiDriver The driver object which provides an abstract factory for creating a concrete drawing engine. + +@pre CDirectGdiDriver object has been initialised from the calling thread. +@post Instances of CDirectGdiContext and MDirectGdiEngine have been created. + +@leave Leaves if CDirectGdiDriver has not been initialised from the calling thread, or other errors occur during object construction. +@return Reference to constructed CDirectGdiContext. +*/ +EXPORT_C CDirectGdiContext* CDirectGdiContext::NewL(CDirectGdiDriver& aDirectGdiDriver) + { + CDirectGdiContext* result = new(ELeave) CDirectGdiContext(aDirectGdiDriver); + CleanupStack::PushL(result); + + // Cache a reference to the driver locally, so that we do not need to use + // the singleton accessor all the time. The singleton accessor utilises TLS + // and hence incurs a performance penalty. + // + result->ConstructL(); + + CleanupStack::Pop(); + return result; + } + + +/** +Installs a rendering engine instance from the supplied driver, records +a reference to the driver (for use by the destructor), and initialises it. + +@pre Invoked by NewL(). +@post Instance of MDirectGdiEngine has been created. + +@leave If CDirectGdiDriver::CreateEngine() returns an error code. +*/ +void CDirectGdiContext::ConstructL() + { + User::LeaveIfError(iDriver.CreateEngine(iEngine)); + Reset(); // Initialise context and engine to default values. + } + + +/** +Object constructor. Declared private for better encapsulation. A factory method is +provided to instantiate this class. This class is not intended for derivation. Binary +compatibility needs to be maintained. + +@param aDirectGdiDriver The driver that coordinates management of DirectGDI resources. + +@pre The driver must be initialised. +@post None. +*/ +EXPORT_C CDirectGdiContext::CDirectGdiContext(CDirectGdiDriver& aDirectGdiDriver) : + iDriver(aDirectGdiDriver) + { + } + + +/** +Unbind current target from drawing context and mark drawing engine for deletion. + +@pre None. +@post Rendering engine has had targets unbound and is marked for deletion. +*/ +EXPORT_C CDirectGdiContext::~CDirectGdiContext() + { + // If an engine has been bound, destroy it through the driver. + if (iEngine) + { + iDriver.DestroyEngine(iEngine); + } + + CleanUpBrushPattern(); + iClippingRegion.Close(); + } + + +/** +Binds a rendering target to this drawing context. + +Subsequent rendering operations after calling this method will apply to the new rendering +target. The clipping region will be reset to none, in other words drawing will be clipped to the +full area of the new target by default, other context states such as pen or brush colour, +font, etc. will remain unchanged. + +This operation could fail, DirectGDI clients should always check the return value when +calling this method. The error state is not modified by this function. + +@param aTarget DirectGDI rendering target. + +@pre Rendering target has been fully constructed. +@post The drawing context is bound to the new rendering target. + +@return KErrNone if successful, KErrNotSupported if target is incompatible with the drawing context, + otherwise one of the system-wide error codes. +*/ +EXPORT_C TInt CDirectGdiContext::Activate(RDirectGdiImageTarget& aTarget) + { + GRAPHICS_TRACE("CDirectGdiContext::Activate"); + TInt err = iEngine->Activate(aTarget); + + iActivated = EFalse; + if (err == KErrNone) + { + iActivated = ETrue; + } + return err; + } + +/** +Disables AutoUpdateJustification state. + +@see CDirectGdiContext::SetJustifyAutoUpdate +*/ +EXPORT_C void CDirectGdiContext::NoJustifyAutoUpdate() + { + GRAPHICS_TRACE("CDirectGdiContext::NoJustifyAutoUpdate"); + iAutoUpdateJustification = EFalse; + } + +/** +Enables AutoUpdateJustification state. +During the text drawing, some text parameters which impact on positioning the text on the screen will be updated and applied +*/ +EXPORT_C void CDirectGdiContext::SetJustifyAutoUpdate() + { + GRAPHICS_TRACE("CDirectGdiContext::SetJustifyAutoUpdate"); + iAutoUpdateJustification = ETrue; + } + +/** +Draws the whole of a CFbsBitmap. Calls BitBlt() with a rectangle set to the extents of aBitmap. + +No scaling or stretching is involved. The current clipping region and drawing mode apply. The +source bitmap can reside in system memory or ROM. Bitmaps in system memory may be compressed +using RLE or Palette compression, and can be in any supported display mode. Please refer to +CFbsBitmap documentation for more details. + +If the client modifies the content of the bitmap after issuing a BitBlt() command, the method +does not guarantee whether the old bitmap content or the new one will be drawn. Clients must call +Finish() on the driver before modifying the bitmap content if they want a guaranteed result that +the previously issued BitBlt() will draw the old bitmap content. + +In the event of a failure, the error state is set to one of the system-wide error codes. + +@see void CDirectGdiContext::BitBlt(const TPoint& aPoint, const CFbsBitmap* aBitmap, const TRect& aSourceRect); +@param aDestPos The position to draw the top left corner of the bitmap. +@param aSourceBitmap The source bitmap. + +@pre The rendering target has been activated. +@post Request to draw the bitmap content has been accepted. There is no guarantee that the request + has been processed when the method returns. + +@panic DGDI 7, if the rendering context has not been activated. +*/ +EXPORT_C void CDirectGdiContext::BitBlt(const TPoint& aDestPos, const CFbsBitmap& aSourceBitmap) + { + GRAPHICS_TRACE2("CDirectGdiContext::BitBlt(%d,%d)", aDestPos.iX, aDestPos.iY); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + + if (ValidateBitmap (aSourceBitmap)) + { + iEngine->BitBlt(aDestPos, aSourceBitmap, TRect(aSourceBitmap.SizeInPixels())); + } + } + + +/** +Draws a particular rectangle from a CFbsBitmap via bitmap block image transfer. +The bitmap content is specified by the given source rectangle. The bitmap content is drawn +into the rendering target starting from the given destination position. To draw the content +of the entire bitmap, a source rectangle TRect(TPoint(0,0), aBitmap.SizeInPixels()) is used. + +The source rectangle is intersected with the source bitmap’s full extent, and the intersection +will become the effective value of the source rectangle. + +No scaling or stretching is involved. The current clipping region and drawing mode apply. The +source bitmap can reside in system memory or ROM. Bitmaps in system memory may be compressed +using RLE or Palette compression, and can be in any supported display mode. Please refer to +CFbsBitmap documentation for more details. + +The bitmap is not guaranteed to continue to exist outside the implementation of this method, for example +DirectGDI clients may delete the bitmap immediately after issuing a BitBlt() command. The adaptation +must maintain its own copy by duplicating the bitmap if access to the bitmap data is required +later on, for example outside this method implementation. Duplicating the bitmap will increase its +reference counter and will prevent the object from being destroyed by Fbserv. The adaptation +must make sure the bitmap copy is destroyed when it is no longer needed. + +If the client modifies the content of the bitmap after issuing BitBlt() command, the method +does not guarantee whether the old bitmap content or the new one will be drawn. Clients must call +Finish() on the driver before modifying the bitmap content if they want a guaranteed result that +the previously issued BitBlt() will draw the old bitmap content. + +In the event of a failure, the error state is set to one of the system-wide error codes. + +@param aDestPos The position to draw the top left corner of the bitmap (destination position). +@param aSourceBitmap The source bitmap. +@param aSourceRect A rectangle defining the piece of the source to be drawn. No image data + is transferred if no intersection exists with the bitmap. + NOTE: The top and left hand edges are inclusive, the bottom and + right hand edge are exclusive. + +@pre The rendering target has been activated. +@post Request to draw the bitmap content has been accepted. There is no guarantee that the request + has been processed when the method returns. + +@panic DGDI 7, if the rendering context has not been activated. +*/ +EXPORT_C void CDirectGdiContext::BitBlt( + const TPoint& aDestPos, + const CFbsBitmap& aSourceBitmap, + const TRect& aSourceRect) + { + GRAPHICS_TRACE2("CDirectGdiContext::BitBlt(%d,%d)", aDestPos.iX, aDestPos.iY); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + + if (ValidateBitmap(aSourceBitmap)) + { + TRect sourceRect = IntersectBitmapWithRect(aSourceBitmap, aSourceRect); + if (!sourceRect.IsEmpty()) + { + iEngine->BitBlt(aDestPos, aSourceBitmap, sourceRect); + } + } + } + +/** +Validates a specified bitmap image. +The bitmap is deemed invalid if its associated handle equals KNullHandle or it +has a width or height of zero. + +The following errors are set in iDirectGdiDriver if the associated conditions are met: + - KErrBadHandle if the handle associated with the bitmap equals KNullHandle. + - KErrArgument is the bitmaps width or height is zero. + +@param aBitmap The bitmap to validate. + +@return ETrue if the specified bitmap is valid, otherwise EFalse. +*/ +TBool CDirectGdiContext::ValidateBitmap(const CFbsBitmap& aBitmap) + { + TInt errorCode = KErrNone; + TBool result = ETrue; + + if (aBitmap.Handle() == KNullHandle) + { + errorCode = KErrBadHandle; + } + else + { + // Check that mask and source bitmap have width and height. + const TSize bitmapSize = aBitmap.SizeInPixels(); + if (!bitmapSize.iWidth || !bitmapSize.iHeight) + { + errorCode = KErrArgument; + } + } + + if (errorCode != KErrNone) + { + iDriver.SetError(errorCode); + result = EFalse; + } + + return result; + } + +/* +Returns a TRect that intersects both the CFbsBitmap and the passed-in TRect. + +@param aBitmap The bitmap to intersect with. +@param aRect The TRect object that is overlapping the bitmap. +@return A TRect that represents the intersection of the two. If the two do not intersect, + it will be an empty TRect object. +*/ +TRect CDirectGdiContext::IntersectBitmapWithRect(const CFbsBitmap& aBitmap, const TRect& aRect) const + { + TRect result = TRect(aBitmap.SizeInPixels()); + + if (aRect == result) + return result; + + if (result.Intersects(aRect)) + { + result.Intersection(aRect); + return result; + } + + return TRect(0,0,0,0); + } + +/** + +Validates the specified source bitmap and mask pair. +First validates the source and mask bitmaps individually, and then checks for valid +bitmap pairings. The only pairing not supported is: EGray256 masks and sources with +an alpha-channel when using EDrawModeWriteAlpha. + +@see CDirectGdiContext::ValidateBitmap() + +The following errors are set in iDirectGdiDriver if the associated conditions are met: + - KErrBadHandle if the handle associated with either bitmap equals KNullHandle. + - KErrArgument if either bitmaps width or height is zero. + - KErrArgument if the mask format is EGray256 and the source contains an alpha-channel and draw mode is EDrawModeWriteAlpha. + +@param aSourceBitmap The source bitmap to validate. +@param aMaskBitmap The mask to validate. + +@return ETrue if the specified bitmaps is valid, otherwise EFalse. +*/ +TBool CDirectGdiContext::ValidateSourceAndMaskBitmaps(const CFbsBitmap& aSourceBitmap, const CFbsBitmap& aMaskBitmap) + { + TInt errorCode = KErrNone; + TBool result = ETrue; + + if (ValidateBitmap (aSourceBitmap) && ValidateBitmap (aMaskBitmap)) + { + TDisplayMode sourceBitmapDisplayMode = aSourceBitmap.DisplayMode(); + + // We do not currently support EGray256 masks and sources with an alpha-channel + // with EDrawModeWriteAlpha. + if ((iDrawMode == DirectGdi::EDrawModeWriteAlpha) && + (aMaskBitmap.DisplayMode() == EGray256) && + ((sourceBitmapDisplayMode == EColor16MA) || (sourceBitmapDisplayMode == EColor16MAP))) + { + errorCode = KErrArgument; + } + } + else + { + result = EFalse; + } + + if (errorCode != KErrNone) + { + iDriver.SetError(errorCode); + result = EFalse; + } + + return result; + } + +/** +Helper method for performing BitBltMasked. +Note that aInvertMask is ignored if aMaskPos is not at 0,0. + +@see CDirectGdiContext::BitBlt(const TPoint& aPoint, const CFbsBitmap& aBitmap, const TRect& aSourceRect); +@see CDirectGdiContext::BitBltMasked(const TPoint&, const CFbsBitmap&,const TRect&, const CFbsBitmap&, const TPoint&); + +@param aDestPos The destination for the top left corner of the transferred bitmap. + It is relative to the top left corner of the destination bitmap, which may be the screen. +@param aSourceBitmap A memory-resident source bitmap. +@param aSourceRect A rectangle defining the piece of the bitmap to be drawn, + with co-ordinates relative to the top left corner of the bitmap. +@param aMaskBitmap Mask bitmap. +@param aInvertMask If EFalse, a source pixel that is masked by a black pixel is not transferred to + the destination rectangle. If ETrue, then a source pixel that is masked by a + white pixel is not transferred to the destination rectangle. If alpha blending + is used instead of masking, this flag is ignored and no inversion takes place. + Note that this parameter is ignored if aMaskPos does not equal TPoint(0,0). +@param aMaskPos The point on the mask bitmap to use as the top left corner +*/ +void CDirectGdiContext::DoBitBltMasked( + const TPoint& aDestPos, + const CFbsBitmap& aSourceBitmap, + const TRect& aSourceRect, + const CFbsBitmap& aMaskBitmap, + TBool aInvertMask, + const TPoint& aMaskPos) + { + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + + if (ValidateSourceAndMaskBitmaps(aSourceBitmap, aMaskBitmap)) + { + // If the source rectangle does not intersect aBitmap, do nothing. + TRect sourceRect = IntersectBitmapWithRect(aSourceBitmap, aSourceRect); + if (!sourceRect.IsEmpty()) + { + if (aMaskPos == TPoint(0, 0)) + { + iEngine->BitBltMasked(aDestPos, aSourceBitmap, sourceRect, aMaskBitmap, aInvertMask); + } + else + { + TSize maskSize = aMaskBitmap.SizeInPixels(); + // Convert negative or large mask offsets into sensible positive ones for tiling. + TPoint maskOffset(aMaskPos.iX % maskSize.iWidth, aMaskPos.iY % maskSize.iHeight); + if (maskOffset.iX < 0) + maskOffset.iX += maskSize.iWidth; + if (maskOffset.iY < 0) + maskOffset.iY += maskSize.iHeight; + + iEngine->BitBltMasked(aDestPos, aSourceBitmap, sourceRect, aMaskBitmap, maskOffset); + } + } + } + } + + +/** +Performs a masked bitmap block transfer. Source rectangle operates in a similar way to BitBlt(). + +This function uses either a black and white (binary) mask bitmap, or if the mask's display mode is +EGray256, alpha blending is used. The result is undefined if the mask pixel value is neither black nor +white and the mask display mode is other than EGray256. + +The mask is aligned with the source bitmap by aligning the first pixel of the mask and source bitmaps within +the source rectangle. Tiling in both directions applies if the mask size is smaller than the source rectangle. +Note that the mask is applied before the piece of the bitmap is defined - the mask is tiled relative to the +top left of the original source bitmap rather than the top left of the bitmap piece. If the mask has zero +width or height, the error state is set to KErrArgument and no drawing is performed. + +The mask bitmap can be used as either a positive or negative mask. Masked pixels are not mapped to the +destination rectangle. + +If the client modifies the contents of the bitmap or the mask after issuing the BitBltMasked() command, the +method does not guarantee whether the old bitmap or mask contents, or the new ones will be used. +Clients must call Finish() on the driver before modifying the bitmap or mask contents if they want a +guaranteed result that the previously issued BitBltMasked() will be using the old bitmap or mask contents. + +In the event of a failure, the error state is set to one of the system-wide error codes. + +@see CDirectGdiContext::BitBlt(const TPoint& aPoint, const CFbsBitmap& aBitmap, const TRect& aSourceRect); +@see CDirectGdiContext::BitBltMasked(const TPoint&, const CFbsBitmap&,const TRect&, const CFbsBitmap&, const TPoint&); + +@param aDestPos The destination for the top left corner of the transferred bitmap. + It is relative to the top left corner of the destination bitmap, which may be the screen. +@param aSourceBitmap A memory-resident source bitmap. +@param aSourceRect A rectangle defining the piece of the bitmap to be drawn, + with co-ordinates relative to the top left corner of the bitmap. +@param aMaskBitmap Mask bitmap. +@param aInvertMask If EFalse, a source pixel that is masked by a black pixel is not transferred to + the destination rectangle. If ETrue, then a source pixel that is masked by a + white pixel is not transferred to the destination rectangle. If alpha blending + is used instead of masking, this flag is ignored and no inversion takes place. + +@pre The rendering target has been activated. aBitmap and aMask hold valid handles. +@post Request to draw the masked bitmap content has been accepted. + There is no guarantee that the request has been processed when the method returns. + +@panic DGDI 7, if the rendering context has not been activated. +*/ +EXPORT_C void CDirectGdiContext::BitBltMasked( + const TPoint& aDestPos, + const CFbsBitmap& aSourceBitmap, + const TRect& aSourceRect, + const CFbsBitmap& aMaskBitmap, + TBool aInvertMask) + { + GRAPHICS_TRACE2("CDirectGdiContext::BitBltMasked(%d,%d)", aDestPos.iX, aDestPos.iY); + DoBitBltMasked (aDestPos, aSourceBitmap, aSourceRect, aMaskBitmap, aInvertMask, TPoint(0, 0)); + } + + +/** +Performs a masked bitmap block transfer. Source rectangle operates in a similar way to BitBlt(). + +This function uses either a black and white (binary) mask bitmap, or if aMaskBitmap's display mode is +EGray256, alpha blending is used. The result is undefined if the mask pixel value is neither black nor +white and the mask display mode is other than EGray256. + +The source rectangle is intersected with the source bitmap’s full extent and the intersection +will become the effective value. The mask bitmap is aligned with the source bitmap by aligning +its pixel at the position specified in aMaskPt with the first pixel of the source bitmap +within the source rectangle. The mask bitmap will be tiled if it is smaller than the source +rectangle. If the mask has zero width or height, the error state is set to KErrArgument and +no drawing is performed. + +If the client modifies the contents of the bitmap or the mask after issuing the BitBltMasked() command, the +method does not guarantee whether the old bitmap or mask contents, or the new ones will be used. +Clients must call Finish() on the driver before modifying the bitmap or mask contents if they want a +guaranteed result that the previously issued BitBltMasked() will be using the old bitmap or mask contents. + +In the event of a failure, the error state is set to one of the system-wide error codes. + +@see CDirectGdiContext::BitBlt(const TPoint& aPoint, const CFbsBitmap& aBitmap, const TRect& aSourceRect); +@see CDirectGdiContext::BitBltMasked(const TPoint&, const CFbsBitmap&,const TRect&, const CFbsBitmap&, TBool); + +@param aDestPos The destination for the top left corner of the transferred bitmap. + It is relative to the top left corner of the destination bitmap, which may be the screen. +@param aSourceBitmap A memory-resident source bitmap. +@param aSourceRect A rectangle defining the piece of the bitmap to be drawn, + with co-ordinates relative to the top left corner of the bitmap. +@param aMaskBitmap Mask bitmap. +@param aMaskPos The point on the mask bitmap to use as the top left corner + +@pre The rendering target has been activated. aBitmap and aMask hold valid handles. +@post Request to draw the masked bitmap content has been accepted. + There is no guarantee that the request has been processed when the method returns. + +@panic DGDI 7, if no context is activated +*/ +EXPORT_C void CDirectGdiContext::BitBltMasked( + const TPoint& aDestPos, + const CFbsBitmap& aSourceBitmap, + const TRect& aSourceRect, + const CFbsBitmap& aMaskBitmap, + const TPoint& aMaskPos) + { + GRAPHICS_TRACE2("CDirectGdiContext::BitBltMasked(%d,%d)", aDestPos.iX, aDestPos.iY); + DoBitBltMasked (aDestPos, aSourceBitmap, aSourceRect, aMaskBitmap, EFalse, aMaskPos); + } + + +/** +Resets the current clipping region to none. + +@see CDirectGdiContext::SetClippingRegion(const TRegion&) + +@pre The rendering target has been activated. +@post Clipping region is reset to none. Subsequent rendering operations on current target will be clipped to the + full area of the target. + +@panic DGDI 7, if the rendering context has not been activated. +*/ +EXPORT_C void CDirectGdiContext::ResetClippingRegion() + { + GRAPHICS_TRACE("CDirectGdiContext::ResetClippingRegion"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + iClippingRegion.Clear(); + iEngine->ResetClippingRegion(); + } + + +/** +Clears the entire target area with the current brush colour. The area is filled +as if ESolidBrush is used. Current clipping region and drawing mode apply. + +@see CDirectGdiContext::Clear(const TRect&) +@see CDirectGdiContext::SetBrushColor(TRgb) +@see CDirectGdiContext::SetDrawMode(DirectGdi::TDrawMode) +@see CDirectGdiContext::SetClippingRegion(const TRegion& aRegion) + +@pre The rendering target has been activated. +@post Request to clear given rectangular area (clipped to current clipping region) + has been accepted. There is no guarantee that the request has been processed + when the method returns. + +@panic DGDI 7, if the rendering context has not been activated. +*/ +EXPORT_C void CDirectGdiContext::Clear() + { + GRAPHICS_TRACE("CDirectGdiContext::Clear"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + iEngine->Clear(); + } + + +/** +Clears the given rectangular area with current brush colour. The area is filled +as if ESolidBrush is used. Current clipping region and drawing mode apply. + +@see CDirectGdiContext::Clear() +@see CDirectGdiContext::SetBrushColor(TRgb) +@see CDirectGdiContext::SetDrawMode(DirectGdi::TDrawMode) +@see CDirectGdiContext::SetClippingRegion(const TRegion&) + +@param aRect Area to be cleared. + +@pre The rendering target has been activated. +@post Request to clear given rectangular area (clipped to current clipping region) has been accepted. + There is no guarantee that the request has been processed when the method returns. + +@panic DGDI 7, if the rendering context has not been activated. +*/ +EXPORT_C void CDirectGdiContext::Clear(const TRect& aRect) + { + GRAPHICS_TRACE2("CDirectGdiContext::Clear(%d,%d)", aRect.Width(), aRect.Height()); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + if(aRect.Width() <= 0 || aRect.Height() <= 0) + { + return; + } + iEngine->Clear(aRect); + } + + +/** +Resets the bitmap brush pattern to none. If the current brush style is EPatternedBrush, the brush +style will be set to ENullBrush. + +@see CDirectGdiContext::SetBrushPattern(const CFbsBitmap&) + +@pre None. +@post The bitmap brush pattern is no longer used. +*/ +EXPORT_C void CDirectGdiContext::ResetBrushPattern() + { + GRAPHICS_TRACE("CDirectGdiContext::ResetBrushPattern"); + CleanUpBrushPattern(); + if (iBrushStyle == DirectGdi::EPatternedBrush) + { + iBrushStyle = DirectGdi::ENullBrush; + iEngine->SetBrushStyle(iBrushStyle); + } + iEngine->ResetBrushPattern(); + } + + +/** +Releases the selected font for this context. + +@pre None. +@post Internal resources previously allocated during SetFont() are released. + +@see CDirectGdiContext::SetFont() +@see CGraphicsContext::DiscardFont() +*/ +EXPORT_C void CDirectGdiContext::ResetFont() + { + GRAPHICS_TRACE("CDirectGdiContext::ResetFont"); + iEngine->ResetFont(); + iFont.Reset(); + } + + +/** +Draws an arc. An arc is a segment of an ellipse which is defined by a given rectangle. The arc is drawn +anti-clockwise from the arc start point to the arc end point. The arc start point is the intersection +between vectors from the centre of the ellipse to the given start position and the ellipse. +Arc end point is defined in the same way. + +@param aRect The rectangle which defines where to draw the ellipse. +@param aStart Position to be used in defining the arc start point. +@param aEnd Position to be used in defining the arc end point. + +@pre The rendering target has been activated. +@post Request to draw an arc has been accepted. There is no guarantee that the request + has been processed when the method returns. + +@panic DGDI 7, if the rendering context has not been activated. + +@see CDirectGdiContext::DrawPie(const TRect&, const TPoint&, const TPoint&) +*/ +EXPORT_C void CDirectGdiContext::DrawArc(const TRect& aRect, const TPoint& aStart, const TPoint& aEnd) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawArc"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + if (aRect.IsEmpty() || iPenStyle == DirectGdi::ENullPen || (iPenSize.iWidth == 0) || (iPenSize.iHeight == 0)) + { + return; + } + iEngine->DrawArc(aRect, aStart, aEnd); + } + + +/** +Draws and fills a pie. A pie is a shape defined by an arc from the ellipse and straight lines +from the centre of the ellipse to the arc start and end position. + +@param aRect The rectangle which defines where to draw the ellipse +@param aStart Position to be used in defining the arc start point +@param aEnd Position to be used in defining the arc end point + +@pre The rendering target has been activated. +@post Request to draw a pie has been accepted. There is no guarantee that the request + has been processed when the method returns. + +@panic DGDI 7, if the rendering context has not been activated. +@panic DGDI 9, if the brush style is EPatternedBrush but no pattern has been set. + +@see CDirectGdiContext::DrawArc(const TRect&, const TPoint&, const TPoint&) +*/ +EXPORT_C void CDirectGdiContext::DrawPie(const TRect& aRect, const TPoint& aStart, const TPoint& aEnd) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawPie"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + GRAPHICS_ASSERT_ALWAYS(iBrushStyle != DirectGdi::EPatternedBrush || iBrushPatternUsed, EDirectGdiPanicBrushPatternNotSet); + + if (aRect.IsEmpty()) + { + return; + } + iEngine->DrawPie(aRect, aStart, aEnd); + } + +/** +Draws the bitmap contents into the destination rectangle. Scaling applies when +the extents of the source bitmap and the destination rectangle do not match. +If the source rectangle is not completely contained within the source +bitmap's extents, no drawing will take place. + +If the client modifies the content of the bitmap after issuing a DrawBitmap() command, +the method does not guarantee that the old bitmap content or the new one +will be drawn. Clients must call Finish() on the driver before modifying the bitmap +content if they want a guarantee that the previously issued DrawBitmap() will draw the +old bitmap content. + +In the event of a failure, the error state is set to one of the system-wide error codes. + +@see CDirectGdiContext::DrawBitmap(const TRect&, const CFbsBitmap&, const TRect&) + +@param aDestRect Destination rectangle. +@param aSourceBitmap Source bitmap. + +@pre The rendering target has been activated. +@post Request to draw the bitmap content has been accepted. + There is no guarantee that the request has been processed when the method returns. + +@panic DGDI 7, if the rendering context has not been activated. +*/ +EXPORT_C void CDirectGdiContext::DrawBitmap(const TRect& aDestRect, const CFbsBitmap& aSourceBitmap) + { + GRAPHICS_TRACE2("CDirectGdiContext::DrawBitmap(%d,%d)", aDestRect.iTl.iX, aDestRect.iTl.iY); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + if (ValidateBitmap (aSourceBitmap)) + { + DrawBitmap(aDestRect, aSourceBitmap,TRect(TPoint(0, 0), aSourceBitmap.SizeInPixels())); + } + } + +/** +Draws the bitmap contents into the destination rectangle. Scaling applies when +the destination and source rectangles do not match. The source bitmap may be +compressed. The destination rectangle will be clipped with the current clipping +region. If the source rectangle is not completely contained within the source +bitmap's extents, no drawing will take place. + +If the client modifies the content of the bitmap after issuing a DrawBitmap() command, +the method does not guarantee that the old bitmap content or the new one +will be drawn. Clients must call Finish() on the driver before modifying the bitmap +content if they want a guarantee that the previously issued DrawBitmap() will draw the +old bitmap content. + +In the event of a failure, the error state is set to one of the system-wide error codes. + +@see CDirectGdiContext::DrawBitmap(const TRect&, const CFbsBitmap&) + +@param aDestRect Destination rectangle. +@param aSourceBitmap Source bitmap. +@param aSourceRect Rectangle specifying the area of the source bitmap to be drawn. + +@pre The rendering target has been activated. +@post Request to draw the bitmap content has been accepted. + There is no guarantee that the request has been processed when the method returns. + +@panic DGDI 7, if the rendering context has not been activated. +*/ +EXPORT_C void CDirectGdiContext::DrawBitmap(const TRect& aDestRect, const CFbsBitmap& aSourceBitmap, const TRect& aSourceRect) + { + GRAPHICS_TRACE2("CDirectGdiContext::DrawBitmap(%d,%d)", aDestRect.iTl.iX, aDestRect.iTl.iY); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + + if (ValidateBitmap(aSourceBitmap)) + { + TSize sourceSize = aSourceBitmap.SizeInPixels(); + // If source rectangle is not fully contained by the extents of the source bitmap, + // or the size of the source bitmap is zero, do nothing. + if (aSourceRect.iTl.iX >= 0 && + aSourceRect.iTl.iY >= 0 && + aSourceRect.iBr.iX <= sourceSize.iWidth && + aSourceRect.iBr.iY <= sourceSize.iHeight && + !aDestRect.IsEmpty() && !aSourceRect.IsEmpty()) + { + iEngine->DrawBitmap(aDestRect, aSourceBitmap, aSourceRect); + } + } + } + + +/** +Draws bitmap content with masking. Scaling applies to both the source bitmap and the mask. +Both the source and the mask bitmap may be compressed. The destination and source rectangles +operate in a similar way to DrawBitmap(). + +This function uses either a black and white (binary) mask bitmap, or if the mask's display mode is +EGray256, alpha blending is used. The result is undefined if the mask pixel value is neither black nor +white and the mask display mode is other than EGray256. + +The mask is aligned with the source bitmap by aligning their first pixels within the source +rectangle. If the mask size is greater than or equal to the source bitmap size, it will be +scaled to fit the destination rectangle in the same way the source bitmap is scaled. +If the mask has zero width or height, the error state is set to KErrArgument and no drawing is performed. + +If the mask is smaller than the source bitmap, it will be tiled to fit the source bitmap size, +and then scaled to fit the destination rectangle. + +If the client modifies the content of the bitmap or mask after issuing a DrawBitmapMasked() command, +the method does not guarantee whether the old bitmap or mask contents, or the new ones +will be used. Clients must call Finish() on the driver before modifying the bitmap or mask contents +if they want a guaranteed result that the previously issued DrawBitmapMasked() will be using the old +bitmap or mask contents. + +In the event of a failure, the error state is set to one of the system-wide error codes. + +@param aDestRect Destination rectangle. +@param aSourceBitmap Source bitmap. +@param aSourceRect Rectangle specifying the area of the source bitmap to be drawn. +@param aMaskBitmap Mask bitmap. +@param aInvertMask If EFalse, a source pixel that is masked by a black pixel is not transferred to + the destination rectangle. If ETrue, then a source pixel that is masked by a + white pixel is not transferred to the destination rectangle. If alpha blending + is used instead of masking, this flag is ignored and no inversion takes place. + +@pre The rendering target has been activated. +@post Request to draw the bitmap content with masking has been accepted. + There is no guarantee that the request has been processed when the method returns. + +@panic DGDI 7, if the rendering context has not been activated. +*/ +EXPORT_C void CDirectGdiContext::DrawBitmapMasked( + const TRect& aDestRect, + const CFbsBitmap& aSourceBitmap, + const TRect& aSourceRect, + const CFbsBitmap& aMaskBitmap, + TBool aInvertMask) + { + GRAPHICS_TRACE2("CDirectGdiContext::DrawBitmapMasked(%d,%d)", aDestRect.iTl.iX, aDestRect.iTl.iY); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + + if (ValidateSourceAndMaskBitmaps(aSourceBitmap, aMaskBitmap)) + { + TSize sourceSize = aSourceBitmap.SizeInPixels(); + // Ensure source rect is fully within bounds of bitmap extents and + // dest and source rect are not empty. + if (aSourceRect.iTl.iX >= 0 && + aSourceRect.iTl.iY >= 0 && + aSourceRect.iBr.iX <= sourceSize.iWidth && + aSourceRect.iBr.iY <= sourceSize.iHeight && + !aDestRect.IsEmpty() && !aSourceRect.IsEmpty()) + { + iEngine->DrawBitmapMasked(aDestRect, aSourceBitmap, aSourceRect, aMaskBitmap, aInvertMask); + } + } + } + +/** +Draws and fills a rectangle with rounded corners. The corner is constructed as an arc of +an ellipse. The outline is drawn in the current pen colour, size and style if the pen +colour is not ENullPen. The area inside the rectangle is filled according to the current +brush colour and style. + +If the corner size has zero width or height, a square-cornered rectangle is drawn. If the corner +size is greater than half the extents of the rectangle, an ellipse is drawn. + +@param aRect The rectangle. +@param aCornerSize The corner size. + +@see CDirectGdiContext::SetPenSize() +@see CDirectGdiContext::SetPenStyle() +@see CDirectGdiContext::SetPenColor() +@see CDirectGdiContext::SetBrushColor() +@see CDirectGdiContext::SetBrushStyle() +@see CDirectGdiContext::SetBrushPattern() + +@pre The rendering target has been activated. +@post Request to draw a rectangle with rounded corners has been accepted. There is no guarantee + that the request has been processed when the method returns. + +@panic DGDI 7, if the rendering context has not been activated. +@panic DGDI 9, if the brush style is EPatternedBrush but no pattern has been set. +*/ +EXPORT_C void CDirectGdiContext::DrawRoundRect(const TRect& aRect, const TSize& aCornerSize) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawRoundRect"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + GRAPHICS_ASSERT_ALWAYS(iBrushStyle != DirectGdi::EPatternedBrush || iBrushPatternUsed, EDirectGdiPanicBrushPatternNotSet); + + TSize ellsize(aCornerSize); + ellsize.iWidth <<= 1; + ellsize.iHeight <<= 1; + + if (aRect.Width() > 0 && aRect.Height() > 0) + { + if (ellsize.iWidth < 3 || ellsize.iHeight < 3) + { + DrawRect(aRect); + return; + } + if (aRect.Width() < ellsize.iWidth && aRect.Height() < ellsize.iHeight) + { + DrawEllipse(aRect); + return; + } + iEngine->DrawRoundRect(aRect, aCornerSize); + } + } + +/** +Draws a polyline using the points in an array. A polyline is a series of concatenated straight +lines joining a set of points. Current pen settings and drawing mode applies. If @c aPointList +has one element, a plot is performed. + +@param aPointList Array of points specifying points on the polyline. + +@pre The rendering target has been activated. +@post Request to draw a polyline has been accepted. + There is no guarantee that the request has been processed when the method returns. + The internal drawing position is set to the last point in the array. + +@panic DGDI 7, if the rendering context has not been activated. + +@see CDirectGdiContext::DrawPolyLineNoEndPoint(const TArray&) +@see CDirectGdiContext::SetPenSize(const TSize&) +@see CDirectGdiContext::SetPenStyle(DirectGdi::TPenStyle) +@see CDirectGdiContext::SetPenColor(TRgb) +@see CDirectGdiContext::SetDrawMode(DirectGdi::TDrawMode) +*/ +EXPORT_C void CDirectGdiContext::DrawPolyLine(const TArray& aPointList) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawPolyLine"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + if ((aPointList.Count() < 1) || iPenStyle == DirectGdi::ENullPen || (iPenSize.iWidth == 0) || (iPenSize.iHeight == 0)) + { + return; + } + + if (aPointList.Count() == 1) + { + Plot(aPointList[0]); + } + else + { + iEngine->DrawPolyLine(aPointList); + } + } + + +/** +Draws a polyline using the points in an array. A polyline is a series of concatenated straight +lines joining a set of points. Current pen settings and drawing mode applies. If @c aPointList +has less than two elements, no drawing is performed. If @c aPointList has exactly two elements +then a DrawLine is performed. + +@param aPointList Array of points specifying points on the polyline. + +@pre The rendering target has been activated. +@post Request to draw a polyline has been accepted. + There is no guarantee that the request has been processed when the method returns. + The internal drawing position is set to the last point in the array. + +@panic DGDI 7, if the rendering context has not been activated. + +@see CDirectGdiContext::DrawPolyLine(const TArray&) +@see CDirectGdiContext::SetPenSize(const TSize&) +@see CDirectGdiContext::SetPenStyle(DirectGdi::TPenStyle) +@see CDirectGdiContext::SetPenColor(TRgb) +@see CDirectGdiContext::SetDrawMode(DirectGdi::TDrawMode) +*/ +EXPORT_C void CDirectGdiContext::DrawPolyLineNoEndPoint(const TArray& aPointList) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawPolyLineNoEndPoint"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + + const TInt points = aPointList.Count(); + + if (points == 1) + { + Plot(aPointList[0]); + } + else if (points == 2) + { + DrawLine(aPointList[0], aPointList[1]); + } + else if (points > 2 && !(iPenStyle == DirectGdi::ENullPen || (iPenSize.iWidth == 0) || (iPenSize.iHeight == 0))) + { + iEngine->DrawPolyLineNoEndPoint(aPointList); + } + } + +/** +Draws and fills a polygon defined using an array of points. The first point in the array defines the +start of the first side of the polygon. The final side of the polygon is drawn using the last point +from the array, and the line is drawn to the start point of the first side. The outline of the polygon +is drawn using the current pen settings and the area is filled with the current brush settings. + +Self-crossing polygons are filled according to the specified fill rule. + +If @c aPointList is empty, no drawing is performed. If it has one element, the result is the same as Plot(). +If it has two elements, the result is the same as DrawLine(). + +The error state is set to KErrArgument if aFillRule is an invalid fill rule. + +@param aPointList Array of points specifying the vertices of the polygon. +@param aFillRule Polygon filling rule. + +@pre The rendering target has been activated. +@post Request to draw a polygon has been accepted. There is no guarantee that the request has been processed + when the method returns. The internal drawing position is set to the last point in the array. + +@panic DGDI 7, if the rendering context has not been activated. +@panic DGDI 9, if the brush style is EPatternedBrush but no pattern has been set. + +@see CDirectGdiContext::SetPenSize(const TSize&) +@see CDirectGdiContext::SetPenStyle(DirectGdi::TPenStyle) +@see CDirectGdiContext::SetPenColor(TRgb) +@see CDirectGdiContext::SetBrushColor(TRgb) +@see CDirectGdiContext::SetBrushStyle(DirectGdi::TBrushStyle) +@see CDirectGdiContext::SetBrushPattern(const CFbsBitmap&) +@see CDirectGdiContext::SetBrushOrigin(TPoint) +@see CDirectGdiContext::SetDrawMode(DirectGdi::TDrawMode) +@see DirectGdi::TFillRule +*/ +EXPORT_C void CDirectGdiContext::DrawPolygon(const TArray& aPointList, DirectGdi::TFillRule aFillRule) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawPolygon"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + GRAPHICS_ASSERT_ALWAYS(iBrushStyle != DirectGdi::EPatternedBrush || iBrushPatternUsed, EDirectGdiPanicBrushPatternNotSet); + + if (aFillRule != DirectGdi::EAlternate && aFillRule != DirectGdi::EWinding) + { + iDriver.SetError(KErrArgument); + return; + } + + if (aPointList.Count() == 0) + { + return; + } + + iEngine->DrawPolygon(aPointList, aFillRule); + } + + +/** +Draws and fills an ellipse inside the given rectangle. Current pen and brush settings apply. + +@see CDirectGdiContext::SetPenSize(const TSize&) +@see CDirectGdiContext::SetPenStyle(DirectGdi::TPenStyle) +@see CDirectGdiContext::SetPenColor(TRgb) +@see CDirectGdiContext::SetBrushColor(TRgb) +@see CDirectGdiContext::SetBrushStyle(DirectGdi::TBrushStyle) +@see CDirectGdiContext::SetBrushPattern(const CFbsBitmap&) + +@param aRect The rectangle in which to draw the ellipse. + +@pre The rendering target has been activated. +@post Request to draw an ellipse has been accepted. + There is no guarantee that the request has been processed when the method returns. + +@panic DGDI 7, if the rendering context has not been activated. +@panic DGDI 9, if the brush style is EPatternedBrush but no pattern has been set. +*/ +EXPORT_C void CDirectGdiContext::DrawEllipse(const TRect& aRect) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawEllipse"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + GRAPHICS_ASSERT_ALWAYS(iBrushStyle != DirectGdi::EPatternedBrush || iBrushPatternUsed, EDirectGdiPanicBrushPatternNotSet); + + if (aRect.IsEmpty()) + { + return; + } + iEngine->DrawEllipse(aRect); + } + + +/** +Draws a straight line from the start to the end position using current pen size, colour and style. + +@param aStart Start position. +@param aEnd End position. + +@pre The rendering target has been activated. +@post Request to draw a straight line with the current pen colour, size and style has been accepted. + There is no guarantee that the request has been processed when the method returns. + The internal drawing position is set to @c aEnd. + +@panic DGDI 7, if the rendering context has not been activated. + +@see CDirectGdiContext::SetPenSize(const TSize&) +@see CDirectGdiContext::SetPenStyle(DirectGdi::TPenStyle) +@see CDirectGdiContext::SetPenColor(TRgb) +@see CDirectGdiContext::SetDrawMode(DirectGdi::TDrawMode) +*/ +EXPORT_C void CDirectGdiContext::DrawLine(const TPoint& aStart, const TPoint& aEnd) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawLine"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + + // Do not draw if start/end at the same point or pensize is 0 + if(aStart == aEnd || iPenStyle == DirectGdi::ENullPen || iPenSize.iWidth == 0 || iPenSize.iHeight == 0) + { + return; + } + + iEngine->DrawLine(aStart, aEnd); + } + + +/** +Draws a straight line from the current internal drawing position to a point using the current pen size, colour and style. + +@param aPoint The end-point of the line. + +@pre Rendering target has been activated. +@post Request to draw a straight line to a specified point with the current pen colour, size and style has been accepted. + There is no guarantee that the request has been processed when the method returns. + Internal drawing position is set to @c aPoint. + +@panic DGDI 7, if the rendering context has not been activated. + +@see CDirectGdiContext::SetPenSize(const TSize&) +@see CDirectGdiContext::SetPenStyle(DirectGdi::TPenStyle) +@see CDirectGdiContext::SetPenColor(TRgb) +@see CDirectGdiContext::SetDrawMode(DirectGdi::TDrawMode) +@see CDirectGdiContext::MoveTo(TPoint) +@see CDirectGdiContext::MoveBy(TPoint) +*/ +EXPORT_C void CDirectGdiContext::DrawLineTo(const TPoint& aPoint) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawLineTo"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + if(iPenStyle == DirectGdi::ENullPen || iPenSize.iWidth == 0 || iPenSize.iHeight == 0) + { + return; + } + iEngine->DrawLineTo (aPoint); + } + + +/** +Draws a straight line relative to the current internal drawing position, using a vector. +The start point of the line is the current internal drawing position. The vector @c aVector +is added to the internal drawing position to give the end point of the line. + +@param aVector The vector to add to the current internal drawing position, giving the end point of the line. + +@pre The rendering target has been activated. +@post The request to draw a straight line using the vector with current pen colour, size and style has been + accepted. There is no guarantee that the request has been processed when the method returns. + The internal drawing position is set to the end of the line. + +@panic DGDI 7, if the rendering context has not been activated. + +@see CDirectGdiContext::SetPenSize(const TSize&) +@see CDirectGdiContext::SetPenStyle(DirectGdi::TPenStyle) +@see CDirectGdiContext::SetPenColor(TRgb) +@see CDirectGdiContext::SetDrawMode(DirectGdi::TDrawMode) +@see CDirectGdiContext::MoveTo(TPoint) +@see CDirectGdiContext::MoveBy(TPoint) +*/ +EXPORT_C void CDirectGdiContext::DrawLineBy(const TPoint& aVector) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawLineBy"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + if(iPenStyle == DirectGdi::ENullPen || iPenSize.iWidth == 0 || iPenSize.iHeight == 0) + { + return; + } + + if (aVector != TPoint(0,0)) + { + iEngine->DrawLineBy(aVector); + } + } + + +/** +Draws and fills a rectangle. The outlines are drawn according to the current pen colour, size and style. +The area inside the rectangle is filled according to the current brush colour and style. + +@see CDirectGdiContext::SetPenSize(const TSize&) +@see CDirectGdiContext::SetPenStyle(DirectGdi::TPenStyle) +@see CDirectGdiContext::SetPenColor(TRgb) +@see CDirectGdiContext::SetBrushColor(TRgb) +@see CDirectGdiContext::SetBrushStyle(DirectGdi::TBrushStyle) +@see CDirectGdiContext::SetBrushPattern(const CFbsBitmap&) + +@param aRect The rectangle. + +@pre The rendering target has been activated. +@post Request to draw a rectangle according to the current pen and brush settings has been accepted. + There is no guarantee that the request has been processed when the method returns. + +@panic DGDI 7, if the rendering context has not been activated. +@panic DGDI 9, if the brush style is EPatternedBrush but no pattern has been set. +*/ +EXPORT_C void CDirectGdiContext::DrawRect(const TRect& aRect) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawRect"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + GRAPHICS_ASSERT_ALWAYS(iBrushStyle != DirectGdi::EPatternedBrush || iBrushPatternUsed, EDirectGdiPanicBrushPatternNotSet); + + if(aRect.IsEmpty()) + return; + + iEngine->DrawRect(aRect); + } + + +/** +Draws text at the last print position. + +@see CDirectGdiContext::SetPenColor(TRgb) +@see CDirectGdiContext::SetBrushColor(TRgb) +@see CDirectGdiContext::SetFont(const CFont*) + +@param aText The text string to be drawn. +@param aParam Parameters used in drawing text. + +@pre The rendering target has been activated. +@post Request to draw the text at the last text position using the current font and pen colour has been accepted. + There is no guarantee that the request has been processed when the method returns. + +@panic DGDI 7, if the rendering context has not been activated. +@panic DGDI 10, if the active font is an outline and/or shadow font and the brush + style is neither ENullBrush nor ESolidBrush. +@panic DGDI 11, if a font has not been set prior to calling DrawText(). +*/ +EXPORT_C void CDirectGdiContext::DrawText(const TDesC& aText, const DirectGdi::TTextParameters* aParam) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawText"); + DrawText(aText, aParam, iLastPrintPosition, DirectGdi::ELeft, CFont::EHorizontal); + } + + +/** +Draws text at the specified text position. + +@see CDirectGdiContext::SetPenColor(TRgb) +@see CDirectGdiContext::SetBrushColor(TRgb) +@see CDirectGdiContext::SetFont(const CFont*) + +@param aText The text string to be drawn. +@param aParam Parameters used in drawing text. +@param aPosition The position to draw at. + +@pre The rendering target has been activated. +@post Request to draw the text at the specified position using the current font and pen colour has been accepted. + There is no guarantee that the request has been processed when the method returns. +@panic DGDI 7, if the rendering context has not been activated. +@panic DGDI 10, if the active font is an outline and/or shadow font and the brush + style is neither ENullBrush nor ESolidBrush. +@panic DGDI 11, if a font has not been set prior to calling DrawText(). +*/ +EXPORT_C void CDirectGdiContext::DrawText(const TDesC& aText, const DirectGdi::TTextParameters* aParam, const TPoint& aPosition) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawText"); + DrawText(aText, aParam, aPosition, DirectGdi::ELeft, CFont::EHorizontal); + } + + +/** +Draws text clipped to the specified rectangle. + +@see CDirectGdiContext::SetPenColor(TRgb) +@see CDirectGdiContext::SetBrushColor(TRgb) +@see CDirectGdiContext::SetFont(const CFont*) + +@param aText The text string to be drawn. +@param aParam Parameters used in drawing text. +@param aClipRect The clipping rectangle. + +@pre The rendering target has been activated. +@post Request to draw the text at the last text position using the current font and pen colour, clipped to the specified rectangle has been accepted. + There is no guarantee that the request has been processed when the method returns. +@panic DGDI 7, if the rendering context has not been activated. +@panic DGDI 10, if the active font is an outline and/or shadow font and + the brush style is neither ENullBrush nor ESolidBrush. +@panic DGDI 11, if a font has not been set prior to calling DrawText(). +*/ +EXPORT_C void CDirectGdiContext::DrawText(const TDesC& aText, const DirectGdi::TTextParameters* aParam, const TRect& aClipRect) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawText"); + DrawText(aText, aParam, iLastPrintPosition, DirectGdi::ELeft, CFont::EHorizontal, &aClipRect); + } + + +/** +Draws text clipped to the specified filled rectangle using a baseline offset, +horizontal alignment and a margin. + +@see CDirectGdiContext::SetPenColor(TRgb) +@see CDirectGdiContext::SetBrushColor(TRgb) +@see CDirectGdiContext::SetFont(const CFont*) + +@param aText The text string to be drawn. +@param aParam Parameters used in drawing text. +@param aClipFillRect The clipping rectangle (this rect will also be filled before text is plotted). +@param aBaselineOffset An offset in pixels for the baseline from the normal position (bottom of the rectangle minus the descent of the font). +@param aAlignment Horizontal alignment option relative to the specified rectangle. +@param aMargin Offset to add to the position as calculated using specified rectangle. + +@pre The rendering target has been activated. +@post Request to draw the text within the filled rectangle using the current font and pen colour, offset and clipped to the specified rectangle has been accepted. + There is no guarantee that the request has been processed when the method returns. +@panic DGDI 7, if the rendering context has not been activated. +@panic DGDI 10, if the active font is an outline and/or shadow font and the brush + style is neither ENullBrush nor ESolidBrush. +@panic DGDI 11, if a font has not been set prior to calling DrawText(). +*/ +EXPORT_C void CDirectGdiContext::DrawText(const TDesC& aText, const DirectGdi::TTextParameters* aParam, const TRect& aClipFillRect, TInt aBaselineOffset, DirectGdi::TTextAlign aAlignment, TInt aMargin) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawText"); + TPoint p(aClipFillRect.iTl); + p.iY += aBaselineOffset; + switch (aAlignment) + { + case DirectGdi::ELeft: + { + p.iX += aMargin; + break; + } + case DirectGdi::ERight: + { + p.iX = aClipFillRect.iBr.iX - aMargin; + break; + } + case DirectGdi::ECenter: + { + p.iX += (aClipFillRect.Width() >> 1) + aMargin; + break; + } + default: + { + iDriver.SetError(KErrArgument); + return; + } + } + DrawText(aText, aParam, p, aAlignment, CFont::EHorizontal, &aClipFillRect, &aClipFillRect); + } + + +/** +The private general DrawText routine that implements all the others. + +@param aText The text to be drawn. +@param aParam Parameters used in drawing text. +@param aPosition The origin of the text. +@param aAlignment Left, centred or right, around aPosition; not used if drawing vertically. +@param aDirection Direction: left to right, right to left, or top to bottom. +@param aClipRect If non-null, used as a clippingrect when the text is drawn. +@param aFillRect If non-null, filled before the text is drawn. + +@panic DGDI 7, if the rendering context has not been activated. +@panic DGDI 10, if the active font is an outline and/or shadow font and the brush + style is neither ENullBrush nor ESolidBrush. +@panic DGDI 11, if a font has not been set prior to calling DrawText(). +*/ +void CDirectGdiContext::DrawText(const TDesC& aText, const DirectGdi::TTextParameters* aParam, const TPoint& aPosition, DirectGdi::TTextAlign aAlignment, + CFont::TTextDirection aDirection, const TRect* aClipRect, const TRect* aFillRect) + { + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + // anything to do? + if (aClipRect && aClipRect->IsEmpty()) + { + iDriver.SetError(KErrArgument); + return; + } + + GRAPHICS_ASSERT_ALWAYS(iFont.Handle() != 0, EDirectGdiPanicNoFontSelected); + // This next check actually covers both bitmap and open fonts + const CBitmapFont* bitmap_font = iFont.Address(); + GRAPHICS_ASSERT_ALWAYS(bitmap_font != 0, EDirectGdiPanicNoFontSelected); + + // measure the text + CFont::TMeasureTextInput measure_text_input; + measure_text_input.iCharJustNum = iCharJustNum; + measure_text_input.iCharJustExcess = iCharJustExcess; + measure_text_input.iWordJustNum = iWordJustNum; + measure_text_input.iWordJustExcess = iWordJustExcess; + measure_text_input.iFlags |= CFont::TMeasureTextInput::EFVisualOrder; + if (aParam) + { + GRAPHICS_ASSERT_ALWAYS(aParam->iStart < aParam->iEnd ,EDirectGdiPanicBadParameter); + measure_text_input.iStartInputChar = aParam->iStart; + measure_text_input.iEndInputChar = Min(aText.Length(),aParam->iEnd); + } + CFont::TMeasureTextOutput measure_text_output; + const TInt advance = iFont.MeasureText(aText, &measure_text_input, &measure_text_output); + TRect text_bounds = measure_text_output.iBounds; + + //for linked fonts need an adjustment to the underline postion + TInt underlineStrikeoutOffset = BaselineCorrection(); + + if (iUnderline == DirectGdi::EUnderlineOn) + { + TInt underline_top = 0; + TInt underline_bottom = 0; + GetUnderlineMetrics(underline_top, underline_bottom); + underline_top+=underlineStrikeoutOffset; + underline_bottom+=underlineStrikeoutOffset; + text_bounds.iTl.iY = Min(text_bounds.iTl.iY, underline_top); + text_bounds.iBr.iY = Max(text_bounds.iBr.iY, underline_bottom); + } + if (iStrikethrough == DirectGdi::EStrikethroughOn) + { + TInt strike_top = 0; + TInt strike_bottom = 0; + GetStrikethroughMetrics(strike_top, strike_bottom); + strike_top+=underlineStrikeoutOffset; + strike_bottom+=underlineStrikeoutOffset; + text_bounds.iTl.iY = Min(text_bounds.iTl.iY, strike_top); + text_bounds.iBr.iY = Max(text_bounds.iBr.iY, strike_bottom); + } + if (iUnderline == DirectGdi::EUnderlineOn || iStrikethrough == DirectGdi::EStrikethroughOn) + { + if (aDirection == CFont::EHorizontal) + { + text_bounds.iTl.iX = Min(text_bounds.iTl.iX, 0); + text_bounds.iBr.iX = Max(text_bounds.iBr.iX, advance); + } + else + { + text_bounds.iTl.iY = Min(text_bounds.iTl.iY, 0); + text_bounds.iBr.iY = Max(text_bounds.iBr.iY, advance); + } + } + + // work out the text origin and new drawing position + TPoint text_origin = aPosition; + if (aDirection != CFont::EVertical) + { + const TInt leftSideBearing = Min(text_bounds.iTl.iX, 0); + const TInt rightSideBearing = Max(text_bounds.iBr.iX, advance); + switch (aAlignment) + { + // We are forbidding side-bearings to leak over the sides here, + // but still keeping the start and end pen positions within bounds. + case DirectGdi::ELeft: + text_origin.iX -= leftSideBearing; + break; + case DirectGdi::ERight: + text_origin.iX -= rightSideBearing; + break; + case DirectGdi::ECenter: + // Centre is the average of left and right + text_origin.iX -= (leftSideBearing + rightSideBearing) >> 1; + break; + default: + iDriver.SetError(KErrArgument); + return; + } + } + iLastPrintPosition = text_origin; + if (aDirection == CFont::EHorizontal) + { + iLastPrintPosition.iX += advance; + } + else + { + iLastPrintPosition.iY += advance; + } + text_origin.iY += bitmap_font->iAlgStyle.iBaselineOffsetInPixels; + text_bounds.Move(text_origin); + text_origin += iOrigin; + + // determine clipping rectangle + TRect clipRect = aClipRect ? *aClipRect : text_bounds; + + // fill the box if necessary + if (aFillRect && (iBrushStyle != DirectGdi::ENullBrush)) + { + TRect fillBox = *aFillRect; + if (fillBox.Intersects(clipRect)) + { + fillBox.Intersection(clipRect); + iEngine->SetPenStyle(DirectGdi::ENullPen); // Fill box, don't outline it + iEngine->DrawRect(fillBox); + iEngine->SetPenStyle(iPenStyle); // Put the pen style back + } + } + if (!aText.Length()) + { + return; + } + + clipRect.Move(iOrigin); + + // decide which drawing routine to call + + TOpenFontMetrics metrics; + iFont.GetFontMetrics(metrics); + const TInt maxwidth = metrics.MaxWidth(); + // extext will be TRUE, if font is underline/strikethrough/anti-aliased or it has shadow/outline effects ON. + // Depending on these properties it will call the proper draw routine. + TBool extext = EFalse; + TBool normaltext = EFalse; + const TBool antiAliased = (bitmap_font->GlyphBitmapType() == EAntiAliasedGlyphBitmap); + const TBool outlineAndShadow = (bitmap_font->GlyphBitmapType() == EFourColourBlendGlyphBitmap); + if (antiAliased || outlineAndShadow ) + { + if ((outlineAndShadow) && !((iBrushStyle == DirectGdi::ENullBrush) || (iBrushStyle == DirectGdi::ESolidBrush))) + { + //For future compatibility it is better if brush style of ENullBrush or ESolidBrush is used + //when drawing outline and shadow fonts. + GRAPHICS_PANIC_ALWAYS(EDirectGdiPanicInvalidBrushStyle); + } + extext = ETrue; + } + else if ((iUnderline == DirectGdi::EUnderlineOn) || (iStrikethrough == DirectGdi::EStrikethroughOn) || (iCharJustNum > 0) || (iWordJustNum > 0)) + extext = ETrue; + else + normaltext = ETrue; + + const TInt charjustexcess = iCharJustExcess; + const TInt charjustnum = iCharJustNum; + const TInt wordjustexcess = iWordJustExcess; + const TInt wordjustnum = iWordJustNum; + + // Set up the parameter block for character positioning. + CFont::TPositionParam param; + param.iDirection = static_cast(aDirection); + param.iText.Set(aText); + TInt endDraw = aText.Length(); + if (aParam) + { + param.iPosInText = aParam->iStart; + endDraw = Min(aText.Length(),aParam->iEnd); + } + else + { + param.iPosInText = 0; + } + param.iPen = text_origin; + + // Draw the text. + if (normaltext) + { + DoDrawText(param, endDraw, clipRect); + } + else if (extext) + { + DoDrawTextEx(param, endDraw, clipRect,underlineStrikeoutOffset); + } + + // Reset the justification parameters to their original values. + // These will be updated as required later in code. + iCharJustExcess = charjustexcess; + iCharJustNum = charjustnum; + iWordJustExcess = wordjustexcess; + iWordJustNum = wordjustnum; + + if (iAutoUpdateJustification) + UpdateJustification(aText, aParam); + } + +/** +Overridden function which draws monochrome text within the given clip rectangle. No rotation applied. +@param aParam Defines glyph code, ligature creation and diacritic placement. +@param aEnd The end position within the text descriptor to draw. +@param aClipRect If not-empty, used as a clippingrect when the text is drawn. +*/ +void CDirectGdiContext::DoDrawText(CFont::TPositionParam& aParam, const TInt aEnd, const TRect& aClipRect) + { + iEngine->BeginDrawGlyph(); + RShapeInfo shapeInfo; + while (aParam.iPosInText < aEnd) + { + if (iFont.GetCharacterPosition2(aParam, shapeInfo)) + { + const CFont::TPositionParam::TOutput* output = aParam.iOutput; + for (TInt i = 0; i < aParam.iOutputGlyphs; ++i, ++output) + iEngine->DrawGlyph(output->iBounds.iTl, output->iCode, output->iBitmap, EMonochromeGlyphBitmap, output->iBitmapSize, aClipRect); // All other parameters are default + } + } + iEngine->EndDrawGlyph(); + + if (shapeInfo.IsOpen()) + shapeInfo.Close(); + } + + +/** +Overridden function which draws monochrome text within the given clip rectangle. +The current rotation and font style (strikethrough, underline) are applied. + +@param aParam Defines glyph code, ligature creation and diacritic placement. +@param aEnd The end position within the text descriptor to draw. +@param aClipRect If not-empty, used as a clipping rect when the text is drawn. +@param aUnderlineStrikethroughOffset the offset for the underline, passed to save calculating this value again +*/ +void CDirectGdiContext::DoDrawTextEx(CFont::TPositionParam& aParam, const TInt aEnd, const TRect& aClipRect, const TInt aUnderlineStrikethroughOffset) + { + TPoint startPen = aParam.iPen; + const CBitmapFont* bitmap_font = iFont.Address(); + TInt underlineTop = 0; + TInt underlineBottom = 0; + if (iUnderline == DirectGdi::EUnderlineOn) + { + GetUnderlineMetrics(underlineTop, underlineBottom); + underlineTop+=aUnderlineStrikethroughOffset; + underlineBottom+=aUnderlineStrikethroughOffset; + } + TInt strikeTop = 0; + TInt strikeBottom = 0; + if (iStrikethrough == DirectGdi::EStrikethroughOn) + { + GetStrikethroughMetrics(strikeTop, strikeBottom); + strikeTop+=aUnderlineStrikethroughOffset; + strikeBottom+=aUnderlineStrikethroughOffset; + } + + iEngine->BeginDrawGlyph(); + RShapeInfo shapeInfo; + while (aParam.iPosInText < aEnd) + { + if (!iFont.GetCharacterPosition2(aParam, shapeInfo)) + { + continue; + } + + TInt adjustment = 0; + if ((iCharJustExcess > 0) && (iCharJustNum > 0)) // character clipping/justification + { + adjustment = CGraphicsContext::JustificationInPixels(iCharJustExcess, iCharJustNum); + } + + const CFont::TPositionParam::TOutput* output = aParam.iOutput; + for (TInt i = 0; i < aParam.iOutputGlyphs; ++i, ++output) + { + //get the character metrics for the glyph type + TOpenFontCharMetrics characterParams; + const TUint8* bitmap; + TSize size; + //note may now be using a glyph code, and not a character + iFont.GetCharacterData(aParam.iOutput[i].iCode,characterParams,bitmap,size); + TGlyphBitmapType glyphType = characterParams.GlyphType(); + + switch (glyphType) + { + case EAntiAliasedGlyphBitmap: + case EFourColourBlendGlyphBitmap: + case EDefaultGlyphBitmap: + iEngine->DrawGlyph(output->iBounds.iTl, output->iCode, output->iBitmap, glyphType, output->iBitmapSize, aClipRect); + break; + + default: + //if the outline or shadow is not specified for the character, then use the font setting for the glyph bitmap type + iEngine->DrawGlyph(output->iBounds.iTl, output->iCode, output->iBitmap, + bitmap_font->GlyphBitmapType(), output->iBitmapSize, aClipRect); + break; + } + } + + if (adjustment) + { + aParam.iPen.iX += adjustment; + } + if ((iWordJustExcess > 0) && (iWordJustNum > 0) && (aParam.iOutput[0].iCode == 0x0020)) // word justification + { + adjustment = CGraphicsContext::JustificationInPixels(iWordJustExcess, iWordJustNum); + aParam.iPen.iX += adjustment; + } + } + iEngine->EndDrawGlyph(); + if (shapeInfo.IsOpen()) + shapeInfo.Close(); + + if (iUnderline == DirectGdi::EUnderlineOn) + { + TRect underlineRect(startPen.iX, startPen.iY + underlineTop, aParam.iPen.iX, startPen.iY + underlineBottom); + FillRect(underlineRect, iPenColor, aClipRect); + } + + if (iStrikethrough == DirectGdi::EStrikethroughOn) + { + TRect strikethroughRect(startPen.iX, startPen.iY + strikeTop, aParam.iPen.iX, startPen.iY + strikeBottom); + FillRect(strikethroughRect, iPenColor, aClipRect); + } + } + + +/** +Fills the given rectangle with the specified colour (subject to the clip rect). +This function is internal and used by the text drawing routines. + +@param aRect The rectangle to fill. +@param aColor The colour to fill it with. +@param aClipRect The clipping rect. +*/ +void CDirectGdiContext::FillRect(const TRect& aRect, const TRgb& aColor, const TRect& aClipRect) + { + TRect fillRect = aRect; + if (fillRect.Intersects(aClipRect)) + { + fillRect.Intersection(aClipRect); + // Override the current settings temporarily + iEngine->SetBrushColor(aColor); + iEngine->SetBrushStyle(DirectGdi::ESolidBrush); + iEngine->SetPenStyle(DirectGdi::ENullPen); // Fill box, don't outline it + fillRect.Move(-iOrigin); + iEngine->DrawRect(fillRect); + // Put things back + iEngine->SetPenStyle(iPenStyle); + iEngine->SetBrushStyle(iBrushStyle); + iEngine->SetBrushColor(iBrushColor); + } + } + + +/** +Draws text at the last print position and then rotates it into a vertical position. + +@param aText The text string to be drawn. +@param aParam Parameters used in drawing text. +@param aUp If ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text is rotated 90 degrees clockwise. + +@panic DGDI 7, if the rendering context has not been activated. +@panic DGDI 10, if the active font is an outline and/or shadow font and the brush + style is neither ENullBrush nor ESolidBrush. +@panic DGDI 11, if a font has not been set prior to calling DrawText(). +*/ +EXPORT_C void CDirectGdiContext::DrawTextVertical(const TDesC& aText, const DirectGdi::TTextParameters* aParam, TBool aUp) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawTextVertical"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + // This next check covers both bitmap and open fonts + const CBitmapFont* bitmapFont = iFont.Address(); + GRAPHICS_ASSERT_ALWAYS(bitmapFont != 0, EDirectGdiPanicNoFontSelected); + TRect clipRect2(0, 0, 0, 0); + TInt baselineOffset = 0; + TInt margin = 0; + CalculateClipRect2PlusBaselineOffsetAndMargin(aText, aParam, iLastPrintPosition, aUp, clipRect2, baselineOffset, margin); + DrawTextVertical(aText, aParam, NULL, &clipRect2, NULL, baselineOffset, -1, aUp, DirectGdi::ELeft, margin); //-1 signifies that text will not be clipped + } + + +/** +Draws text vertically from the specified position. + +@param aText The text string to be drawn. +@param aParam Parameters used in drawing text. +@param aPosition A point specifying the position of the left end of the text. +@param aUp If ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text is rotated 90 degrees clockwise. + +@panic DGDI 7, if the rendering context has not been activated. +@panic DGDI 10, if the active font is an outline and/or shadow font and the brush style is neither + ENullBrush nor ESolidBrush. +@panic DGDI 11, if a font has not been set prior to calling DrawText(). +*/ +EXPORT_C void CDirectGdiContext::DrawTextVertical(const TDesC& aText, const DirectGdi::TTextParameters* aParam, const TPoint& aPosition, TBool aUp) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawTextVertical"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + // This next check covers both bitmap and open fonts + const CBitmapFont* bitmapFont = iFont.Address(); + GRAPHICS_ASSERT_ALWAYS(bitmapFont != 0, EDirectGdiPanicNoFontSelected); + TRect clipRect2(0, 0, 0, 0); + TInt baselineOffset = 0; + TInt margin = 0; + CalculateClipRect2PlusBaselineOffsetAndMargin(aText, aParam, aPosition, aUp, clipRect2, baselineOffset, margin); + DrawTextVertical(aText, aParam, NULL, &clipRect2, NULL, baselineOffset, -1, aUp, DirectGdi::ELeft, margin);//-1 signifies that text will not be clipped + } + + +/** +Draws text clipped to the specified rectangle and then rotates it into a vertical position. + +@param aText The text string to be drawn. +@param aParam Parameters used in drawing text. +@param aClipRect The clipping rectangle. +@param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text is rotated 90 degrees clockwise. + +@panic DGDI 7, if the rendering context has not been activated. +@panic DGDI 10, if the active font is an outline and/or shadow font and the brush style is neither ENullBrush + nor ESolidBrush. +@panic DGDI 11, if a font has not been set prior to calling DrawText(). +*/ +EXPORT_C void CDirectGdiContext::DrawTextVertical(const TDesC& aText, const DirectGdi::TTextParameters* aParam, const TRect& aClipRect, TBool aUp) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawTextVertical"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + // This next check covers both bitmap and open fonts + const CBitmapFont* bitmapFont = iFont.Address(); + GRAPHICS_ASSERT_ALWAYS(bitmapFont != 0, EDirectGdiPanicNoFontSelected); + TRect clipRect2(0, 0, 0, 0); + TInt baselineOffset = 0; + TInt margin = 0; + CalculateClipRect2PlusBaselineOffsetAndMargin(aText, aParam, iLastPrintPosition, aUp, clipRect2, baselineOffset, margin); + DrawTextVertical(aText, aParam, &aClipRect, &clipRect2, NULL, baselineOffset, -1, aUp, DirectGdi::ELeft, margin); + } + + +/** +Private internal function for calculating several parameters needed by these routines. + +@param aText The text string to be drawn. +@param aParam Parameters used in drawing text. +@param aPosition A point specifying the position of the left end of the text. +@param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text is rotated 90 degrees clockwise. +@param aClipRect2 On return, contains clipping rectangle. +@param aBaselineOffset On return, contains baseline offset. +@param aMargin On return, contains margin. +*/ +void CDirectGdiContext::CalculateClipRect2PlusBaselineOffsetAndMargin(const TDesC& aText, const DirectGdi::TTextParameters* aParam, const TPoint& aPosition, TBool aUp, TRect& aClipRect2, TInt& aBaselineOffset, TInt& aMargin) + { + TOpenFontMetrics metrics; + iFont.GetFontMetrics(metrics); + aBaselineOffset = metrics.MaxHeight(); + TInt height = aBaselineOffset + metrics.MaxDepth(); + // The next few lines do much the same as TextWidthInPixels but pass + // the text in visual order instead of logical order and also take + // full account of left and right side bearings on the text + CFont::TMeasureTextOutput output; + CFont::TMeasureTextInput input; + input.iFlags = CFont::TMeasureTextInput::EFVisualOrder; + if (aParam) + { + GRAPHICS_ASSERT_ALWAYS(aParam->iStart < aParam->iEnd ,EDirectGdiPanicBadParameter); + input.iStartInputChar = aParam->iStart; + input.iEndInputChar = Min(aText.Length(),aParam->iEnd); + } + TInt advance = iFont.MeasureText(aText, &input, &output); + TInt leftBearing = output.iBounds.iTl.iX; + TInt rightBearing = advance - output.iBounds.iBr.iX; + aMargin = 0; + if (aUp) + { + aClipRect2.iTl.iX = aPosition.iX - aBaselineOffset; + aClipRect2.iTl.iY = aPosition.iY - advance; + aClipRect2.iBr.iX = aPosition.iX + height - aBaselineOffset + 1; + aClipRect2.iBr.iY = aPosition.iY; + if (leftBearing < 0) + { + aClipRect2.iBr.iY -= leftBearing; + aMargin = -leftBearing; + } + if (rightBearing < 0) + { + aClipRect2.iTl.iY += rightBearing; + } + } + else + { + aClipRect2.iTl.iX = aPosition.iX + aBaselineOffset- height; + aClipRect2.iTl.iY = aPosition.iY; + aClipRect2.iBr.iX = aPosition.iX + aBaselineOffset + 1; + aClipRect2.iBr.iY = aPosition.iY + advance; + if (leftBearing < 0) + { + aClipRect2.iTl.iY += leftBearing; + aMargin = -leftBearing; + } + if (rightBearing < 0) + { + aClipRect2.iBr.iY -= rightBearing; + } + } + } + + +/** +Draws text vertically, clipped to a specified rectangle, using a baseline offset, alignment and margin. + +@param aText The text string to be drawn. +@param aParam Parameters used in drawing text. +@param aClipFillRect The clipping rectangle (this rect will also be filled before text is plotted). +@param aBaselineOffset Number of pixels to offset the baseline by. +@param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text is rotated 90 degrees clockwise. +@param aVert Vertical alignment of the text relative to the specified rectangle. +@param aMargin Offset of the text from the position within the rectangle, using the specified alignment. + +@panic DGDI 7, if the rendering context has not been activated. +@panic DGDI 10, if the active font is an outline and/or shadow font and the brush style is neither ENullBrush + nor ESolidBrush. +@panic DGDI 11, if a font has not been set prior to calling DrawText(). +*/ +EXPORT_C void CDirectGdiContext::DrawTextVertical(const TDesC& aText, const DirectGdi::TTextParameters* aParam, const TRect& aClipFillRect, TInt aBaselineOffset, + TBool aUp, DirectGdi::TTextAlign aVert, TInt aMargin) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawTextVertical"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + // This next check covers both bitmap and open fonts + const CBitmapFont* bitmapFont = iFont.Address(); + GRAPHICS_ASSERT_ALWAYS(bitmapFont != 0, EDirectGdiPanicNoFontSelected); + DrawTextVertical(aText, aParam, NULL, &aClipFillRect, &aClipFillRect, aBaselineOffset, -1, aUp, aVert, aMargin); + } + + +/** +Draws text vertically, clipped to a specified rectangle, using a baseline offset, alignment and margin. + +@param aText The text string to be drawn. +@param aParam Parameters used in drawing text. +@param aClipFillRect The clipping rectangle (this rect will also be filled before text is plotted). +@param aBaselineOffset Number of pixels to offset the baseline by. +@param aTextWidth Number of pixels to clip the text to. +@param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text is rotated 90 degrees clockwise. +@param aVert Vertical alignment of the text relative to the specified rectangle. +@param aMargin Offset of the text from the position within the rectangle, using the specified alignment. + +@panic DGDI 7, if the rendering context has not been activated. +@panic DGDI 10, if the active font is an outline and/or shadow font and the brush style is neither ENullBrush + nor ESolidBrush. +@panic DGDI 11, if a font has not been set prior to calling DrawText(). +*/ +EXPORT_C void CDirectGdiContext::DrawTextVertical(const TDesC& aText, const DirectGdi::TTextParameters* aParam, const TRect& aClipFillRect, TInt aBaselineOffset, + TInt aTextWidth, TBool aUp, DirectGdi::TTextAlign aVert, TInt aMargin) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawTextVertical"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + // This next check covers both bitmap and open fonts + const CBitmapFont* bitmapFont = iFont.Address(); + GRAPHICS_ASSERT_ALWAYS(bitmapFont != 0, EDirectGdiPanicNoFontSelected); + DrawTextVertical(aText, aParam, NULL, &aClipFillRect, &aClipFillRect, aBaselineOffset, aTextWidth, aUp, aVert, aMargin); + } + + +/** +The private general DrawTextVertical() routine that implements all the others. +Two clipping rectangles received from different routines. The final rectangle will be calculated as intersection +of first and second clipping rectangle. If aClipRect2 is empty, the error state is set to KErrArgument. + +@param aText The text string to be drawn. +@param aParam Parameters used in drawing text. +@param aClipRect1 Pointer to first clipping rectangle. +@param aClipRect2 Pointer to second clipping rectangle. +@param aFillRect Pointer to rectangle to be filled before text plotting. +@param aBaselineOffset Number of pixels to offset the baseline by. +@param aTextWidth Number of pixels to clip the text to. If negative, the text will not be clipped +@param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text is rotated 90 degrees clockwise. +@param aVert Vertical alignment of the text relative to the specified rectangle. +@param aMargin Offset of the text from the position within the rectangle, using the specified alignment. + +@panic DGDI 10, if the active font is an outline and/or shadow font and the brush style is neither ENullBrush + nor ESolidBrush. +@panic DGDI 11, if a font has not been set prior to calling DrawText(). +@panic DGDI 22, if aClipRect2 is NULL. +*/ +void CDirectGdiContext::DrawTextVertical(const TDesC& aText, const DirectGdi::TTextParameters* aParam, const TRect* aClipRect1, const TRect* aClipRect2, const TRect* aFillRect, + TInt aBaselineOffset, TInt aTextWidth, TBool aUp, DirectGdi::TTextAlign aVert, TInt aMargin) + { + GRAPHICS_ASSERT_ALWAYS(aClipRect2, EDirectGdiPanicBadParameter); + + TRect clipRect2 = *aClipRect2; + clipRect2.Move(iOrigin); + + TRect clipRect(clipRect2); + if (aClipRect1 != NULL) + { + if(aClipRect1->IsEmpty()) + { + iDriver.SetError(KErrArgument); + return; + } + TRect clipRect1 = *aClipRect1; + clipRect1.Move(iOrigin); + clipRect.Intersection(clipRect1); + } + + if ((aFillRect != NULL) && (iBrushStyle != ENullBrush)) + { + // fill the box if necessary + TRect fillBox = *aFillRect; + fillBox.Move(iOrigin); + if (fillBox.Intersects(clipRect)) + { + fillBox.Intersection(clipRect); + iEngine->SetPenStyle(DirectGdi::ENullPen); // Fill box, don't outline it + iEngine->DrawRect(*aFillRect); + iEngine->SetPenStyle(iPenStyle); // Put the pen style back + } + } + if (!aText.Length()) + { + return; + } + if (aClipRect2->IsEmpty()) + { + iDriver.SetError(KErrArgument); + return; + } + + const CBitmapFont* bitmapFont = iFont.Address(); + GRAPHICS_ASSERT_ALWAYS(bitmapFont != 0, EDirectGdiPanicNoFontSelected); + + CFont::TMeasureTextInput input; + //CFont::TMeasureTextOutput + if (aParam) + { + GRAPHICS_ASSERT_ALWAYS(aParam->iStart < aParam->iEnd ,EDirectGdiPanicBadParameter); + input.iStartInputChar = aParam->iStart; + input.iEndInputChar = Min(aText.Length(),aParam->iEnd); + } + TInt width = iFont.MeasureText(aText,&input); + TOpenFontMetrics metrics; + iFont.GetFontMetrics(metrics); + + if (aTextWidth < 0) + { + aTextWidth = width; + } + TPoint coords; + coords.iX = clipRect2.iTl.iX; + TInt directionalMultiplier = aUp ? -1 : 1; + coords.iY = aUp ? clipRect2.iBr.iY - 1 : clipRect2.iTl.iY; + // + // iX calculation, for example: ascent(a)=18 descent(d)=2 size=boxwidth=fontheight(h)=20 baseline=ascent + // pre: iX = 0 + // + // hhhhhhhhhhhhhhhhhhhh + // 01234567890123456789 + // aaaaaaaaaaaaaaaaaadd aUp=ETrue + // ^ + // iX = 18 (baseline) + // + // ddaaaaaaaaaaaaaaaaaa aUp=EFalse + // ^ + // iX = 1 (instead of 2 ie 20-18-1 which is boxwidth-baseline-1) + // + coords.iX += aUp ? aBaselineOffset : clipRect2.Width() - aBaselineOffset - 1; + switch (aVert) + { + case DirectGdi::ELeft: + coords.iY += aMargin * directionalMultiplier; + break; + case DirectGdi::ECenter: + coords.iY += (((clipRect2.iBr.iY - clipRect2.iTl.iY - aTextWidth) >> 1) + aMargin) * directionalMultiplier; + break; + case DirectGdi::ERight: + coords.iY += (clipRect2.iBr.iY - clipRect2.iTl.iY - aTextWidth - aMargin) * directionalMultiplier; + break; + default: + iDriver.SetError(KErrArgument); + return; + } + iLastPrintPosition = coords; + coords.iX += bitmapFont->iAlgStyle.iBaselineOffsetInPixels * directionalMultiplier; + TInt prewidth = width + iCharJustExcess + iWordJustExcess; + iLastPrintPosition.iY -= aUp ? prewidth - 1 : -prewidth; + if (clipRect.IsEmpty() || !width) + { + if (iAutoUpdateJustification) + { + UpdateJustificationVertical(aText, aParam, aUp); + } + return; + } + + /* + Set up the parameter block for character positioning. + Draw left to right, because although the text is being drawn vertically, + it is done by rotating the baseline 90 degrees and drawing in the ordinary way, not by drawing + the characters in their normal orientation but in a vertical column. + */ + CFont::TPositionParam param; + param.iText.Set(aText); + param.iPen = coords; + TInt endDraw = aText.Length(); + if (aParam) + { + param.iPosInText = aParam->iStart; + endDraw = Min(aText.Length(),aParam->iEnd); + } + else + { + param.iPosInText = 0; + } + + // Draw the text. + DoDrawTextVertical(param, aUp, endDraw, clipRect); + if(iAutoUpdateJustification) + { + UpdateJustificationVertical(aText, aParam, aUp); + } + } + + +/** +Draws vertical text within the clipping area + +@param aParam Defines glyph code, ligature creation and diacritic placement +@param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text is rotated 90 degrees clockwise. +@param aEnd The end position within the text descriptor to draw. +@param aClipRect The clipping rectangle. + +@pre iFont is a valid CFont. + +@panic DGDI 13, if the active font is an outline and/or shadow font and the brush style is neither ENullBrush + nor ESolidBrush. +*/ +void CDirectGdiContext::DoDrawTextVertical(CFont::TPositionParam& aParam, TBool aUp, const TInt aEnd, TRect& aClipRect) + { + const CBitmapFont* bitmapFont = iFont.Address(); + if ((bitmapFont->GlyphBitmapType() == EFourColourBlendGlyphBitmap) && !((iBrushStyle == DirectGdi::ENullBrush) || (iBrushStyle == DirectGdi::ESolidBrush))) + { + //For future compatibility it is better if brush style of ENullBrush or ESolidBrush is used + //when drawing outline and shadow fonts. + GRAPHICS_PANIC_ALWAYS(EDirectGdiPanicInvalidBrushStyle); + } + + TPoint startPen = aParam.iPen; + TInt charClipping = aClipRect.iTl.iY; + TInt underlineTop = 0; + TInt underlineBottom = 0; + + //for linked fonts need an adjustment to the underline postion + TInt underlineStrikeoutOffset = BaselineCorrection(); + + if (iUnderline == DirectGdi::EUnderlineOn) + { + GetUnderlineMetrics(underlineTop, underlineBottom); + underlineTop+=underlineStrikeoutOffset; + underlineBottom+=underlineStrikeoutOffset; + } + TInt strikeTop = 0; + TInt strikeBottom = 0; + if (iStrikethrough == DirectGdi::EStrikethroughOn) + { + GetStrikethroughMetrics(strikeTop, strikeBottom); + strikeTop+=underlineStrikeoutOffset; + strikeBottom+=underlineStrikeoutOffset; + } + + const DirectGdi::TGraphicsRotation rotation = aUp ? DirectGdi::EGraphicsRotation270 : DirectGdi::EGraphicsRotation90; + iEngine->BeginDrawGlyph(); + RShapeInfo shapeInfo; + while (aParam.iPosInText < aEnd) + { + TPoint startPen2 = aParam.iPen; + if (!iFont.GetCharacterPosition2(aParam, shapeInfo)) + { + continue; + } + Rotate(aParam.iPen, startPen2, aUp); + TInt adjustment = 0; + if(iCharJustExcess && (iCharJustNum > 0)) // character clipping/justification + { + adjustment = CGraphicsContext::JustificationInPixels(iCharJustExcess, iCharJustNum); + if (adjustment < 0) + { + aClipRect.iTl.iY = aParam.iPen.iY + (aUp ? -adjustment : adjustment); + } + } + + CFont::TPositionParam::TOutput* output = aParam.iOutput; + for (TInt i = 0; i < aParam.iOutputGlyphs; i++, output++) + { + Rotate(output->iBounds.iTl, startPen2, aUp); + + //get the character metrics for the glyph type + TOpenFontCharMetrics characterParams; + const TUint8* bitmap; + TSize size; + //note may now be using a glyph code, and not a character + iFont.GetCharacterData(aParam.iOutput[i].iCode,characterParams,bitmap,size); + TGlyphBitmapType glyphType = characterParams.GlyphType(); + + switch (glyphType) + { + case EAntiAliasedGlyphBitmap: + case EFourColourBlendGlyphBitmap: + case EDefaultGlyphBitmap: + iEngine->DrawGlyph(output->iBounds.iTl, output->iCode, output->iBitmap, glyphType, output->iBitmapSize, aClipRect, rotation); + break; + + default: + //if the outline or shadow is not specified for the character, then use the font setting + iEngine->DrawGlyph(output->iBounds.iTl, output->iCode, output->iBitmap, bitmapFont->GlyphBitmapType(), output->iBitmapSize, aClipRect, rotation); + break; + } + } + + aClipRect.iTl.iY = charClipping; + if (adjustment) + { + aParam.iPen.iY += aUp ? -adjustment : adjustment; + } + if ((iWordJustExcess > 0) && (iWordJustNum > 0) && (aParam.iOutput[0].iCode == 0x0020)) // word justification + { + adjustment = CGraphicsContext::JustificationInPixels(iWordJustExcess, iWordJustNum); + aParam.iPen.iY += aUp ? -adjustment : adjustment; + } + } + iEngine->EndDrawGlyph(); + if (shapeInfo.IsOpen()) + { + shapeInfo.Close(); + } + + if (iUnderline == DirectGdi::EUnderlineOn) + { + TRect underlineRect; // underline + if (aUp) + { + underlineRect.SetRect(startPen.iX + underlineTop, aParam.iPen.iY, startPen.iX + underlineBottom, startPen.iY + 1); + underlineRect.iTl.iY = underlineRect.iBr.iY - underlineRect.Height(); + } + else + { + underlineRect.SetRect(startPen.iX - underlineBottom, startPen.iY, startPen.iX - underlineTop, aParam.iPen.iY); + underlineRect.iBr.iY = underlineRect.iTl.iY + underlineRect.Height(); + underlineRect.iTl.iX++; // adjust for rect not including last line + underlineRect.iBr.iX++; + } + FillRect(underlineRect, iPenColor, aClipRect); + } + + if (iStrikethrough == DirectGdi::EStrikethroughOn) + { + TRect strikethroughRect; // strikethrough + if (aUp) + { + strikethroughRect.SetRect(startPen.iX + strikeTop, aParam.iPen.iY, startPen.iX + strikeBottom, startPen.iY + 1); + strikethroughRect.iTl.iY = strikethroughRect.iBr.iY - strikethroughRect.Height(); + } + else + { + strikethroughRect.SetRect(startPen.iX - strikeBottom, startPen.iY, startPen.iX - strikeTop, aParam.iPen.iY); + strikethroughRect.iBr.iY = strikethroughRect.iTl.iY + strikethroughRect.Height(); + strikethroughRect.iTl.iX++; + strikethroughRect.iBr.iX++; + } + FillRect(strikethroughRect, iPenColor, aClipRect); + } + } + + +/** +Transform a vector, defined by a point relative to an origin, from left-to-right to up or down. + +@param aPoint A point relative to the origin aOrigin. +@param aOrigin The origin to use when transforming the point aPoint. +@param aUp If ETrue, then transform the point from left-right to up, otherwise transform from +left-right to down. +*/ +void CDirectGdiContext::Rotate(TPoint& aPoint, const TPoint& aOrigin, TBool aUp) + { + TInt dx = aPoint.iX - aOrigin.iX; + TInt dy = aPoint.iY - aOrigin.iY; + if (aUp) + { + aPoint.iX = aOrigin.iX + dy; + aPoint.iY = aOrigin.iY - dx; + } + else + { + aPoint.iX = aOrigin.iX - dy; + aPoint.iY = aOrigin.iY + dx; + } + } + + +/** +Can be used to find out the top and bottom of an underline for the active font. +This allows correct calculation of the area required in which to draw text with underline. + +@param aTop The top of the underline position. +@param aBottom The bottom of the underline position. +*/ +void CDirectGdiContext::GetUnderlineMetrics(TInt& aTop, TInt& aBottom) + { + const TInt width = Max((iFont.HeightInPixels() / 10), 1); + aTop = 1 + (width >> 1); + aBottom = aTop + width; + } + + +/** +Get the top and bottom of a strikethrough line for the current font, relative to the baseline. + +@param aTop The top of the strikethrough position. +@param aBottom The bottom of the strikethrough position. +*/ +void CDirectGdiContext::GetStrikethroughMetrics(TInt& aTop, TInt& aBottom) + { + aTop = -(iFont.AscentInPixels() * 5/12) - 1; + aBottom = aTop + Max((iFont.HeightInPixels() / 10), 1); + } + + +/** +Moves the internal drawing position relative to the co-ordinate origin, without drawing a line. +A subsequent call to DrawLineTo() or DrawLineBy() will then use the new internal drawing position +as the start point for the line drawn. + +The operations DrawLine(), DrawLineTo(), DrawLineBy() and DrawPolyline() also change the internal drawing +position to the last point of the drawn line(s). The internal drawing position is set to the co-ordinate +origin if no drawing or moving operations have yet taken place. + +@see CDirectGdiContext::MoveBy(const TPoint&) + +@param aPoint The point to move the internal drawing position to. + +@pre The rendering target has been activated. +@post Request to move the internal drawing position to the specified point has been accepted. + There is no guarantee that the request has been processed when the method returns. + +@panic DGDI 7, if the rendering context has not been activated. +*/ +EXPORT_C void CDirectGdiContext::MoveTo(const TPoint& aPoint) + { + GRAPHICS_TRACE2("CDirectGdiContext::MoveTo(%d,%d)", aPoint.iX, aPoint.iY); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + iEngine->MoveTo(aPoint); + } + + +/** +Moves the internal drawing position by a vector, relative to the current position, without drawing a line. +A subsequent call to DrawLineTo() or DrawLineBy() will then use the new internal drawing position +as the start point for the line drawn. + +The operations DrawLine(), DrawLineTo(), DrawLineBy() and DrawPolyline() also change the internal drawing +position to the last point of the drawn line(s). The internal drawing position is set to the co-ordinate +origin if no drawing or moving operations have yet taken place. + +@see CDirectGdiContext::MoveTo(const TPoint&) + +@param aVector The vector to move the internal position by. + +@pre The rendering target has been activated. +@post Request to move the internal drawing position by a vector has been accepted. + There is no guarantee that the request has been processed when the method returns. +@panic DGDI 7, if the rendering context has not been activated. +*/ +EXPORT_C void CDirectGdiContext::MoveBy(const TPoint& aVector) + { + GRAPHICS_TRACE2("CDirectGdiContext::MoveBy(%d,%d)", aVector.iX, aVector.iY); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + if (aVector != TPoint(0,0)) + { + iEngine->MoveBy(aVector); + } + } + + +/** +Draws a point at given location using current pen colour and size. +If the pen size is greater than 1x1 pixel, a filled circle/ellipse with current pen +colour should be drawn with the given position as the centre. + +@param aPoint The position to plot. + +@pre The rendering target has been activated. +@post Request to draw a point or filled circle/ellipse has been accepted. + There is no guarantee that the request has been processed when the method returns. + +@panic DGDI 7, if the rendering context has not been activated. + +@see CDirectGdiContext::SetPenSize(const TSize&) +@see CDirectGdiContext::SetPenColor(TRgb) +@see CDirectGdiContext::SetDrawMode(DirectGdi::TDrawMode) +*/ +EXPORT_C void CDirectGdiContext::Plot(const TPoint& aPoint) + { + GRAPHICS_TRACE2("CDirectGdiContext::Plot(%d,%d)", aPoint.iX, aPoint.iY); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + if (iPenStyle == DirectGdi::ENullPen || iPenSize.iWidth == 0 || iPenSize.iHeight == 0) + { + return; + } + iEngine->Plot(aPoint); + } + + +/** +Resets drawing state to its default settings. This operation does not unbind the current target. +@pre None. +@post The drawing state is reset to default values. Subsequent drawing will use the default settings until they are changed to different values. +*/ +EXPORT_C void CDirectGdiContext::Reset() + { + GRAPHICS_TRACE("CDirectGdiContext::Reset"); + iEngine->Reset(); + + // Explicit calls are made to the engine to apply the defaults. + // Set() methods should generally not be used as they perform unnecessary checks, and may also + // block the call to the engine if the value being set is the same as the constructor's default. + // Clipping regions. + iClippingRegion.Clear(); + iEngine->ResetClippingRegion(); + // Origin. + iOrigin.SetXY(0,0); + iEngine->SetOrigin(iOrigin); + // Font. + iEngine->ResetFont(); + iFont.Reset(); + // Text. + iLastPrintPosition.SetXY(0,0); + iAutoUpdateJustification = ETrue; + SetCharJustification(0, 0); + SetWordJustification(0, 0); + SetStrikethroughStyle(DirectGdi::EStrikethroughOff); + SetUnderlineStyle(DirectGdi::EUnderlineOff); + // Pen colour. + iPenColor = KRgbBlack; + iEngine->SetPenColor(iPenColor); + // Pen size. + iPenSize = TSize(1,1); + iEngine->SetPenSize(iPenSize); + // Pen style. + iPenStyle = DirectGdi::ESolidPen; + iEngine->SetPenStyle(iPenStyle); + // Draw mode. + iDrawMode = DirectGdi::EDrawModePEN; + iEngine->SetDrawMode(iDrawMode); + // Text shadow colour. + iTextShadowColor = KRgbGray; + iEngine->SetTextShadowColor(iTextShadowColor); + // Brush colour. + iBrushColor = KRgbWhite; + iEngine->SetBrushColor(iBrushColor); + // Brush style. + iBrushStyle = DirectGdi::ENullBrush; + iEngine->SetBrushStyle(iBrushStyle); + // Brush pattern. + CleanUpBrushPattern(); + iEngine->ResetBrushPattern(); + iBrushPatternUsed = EFalse; + // Brush origin. + iBrushOrigin.SetXY(0,0); + iEngine->SetBrushOrigin(iBrushOrigin); + // Internal drawing position. + iEngine->MoveTo(TPoint(0,0)); + } + + +/** +Sets the colour for clearing, filling the area of shapes and the background of text boxes. + +The default brush colour is white. However, the default brush style is ENullBrush, so when drawing +to a target the default appears to be the target's background colour. + +@see CDirectGdiContext::Clear() +@see CDirectGdiContext::Clear(const TRect&) +@see CDirectGdiContext::DrawRect() +@see CDirectGdiContext::DrawRoundRect() +@see CDirectGdiContext::DrawPolygon() +@see CDirectGdiContext::DrawPie() + +@param aColor Brush colour. + +@pre None. +@post The new brush colour will be used on subsequent drawing operations if a brush style making + use of the brush colour is used. The new brush colour remains in effect until another SetBrushColor() + with a different parameter is called. +*/ +EXPORT_C void CDirectGdiContext::SetBrushColor(const TRgb& aColor) + { + GRAPHICS_TRACE1("CDirectGdiContext::SetBrushColor(%d)", aColor.Internal()); + if (aColor != iBrushColor) + { + iBrushColor = aColor; + iEngine->SetBrushColor(iBrushColor); + } + } + + +/** +Sets the brush pattern origin which specifies the start of a pattern tile. +Shapes can be considered as a view port into a continuous pattern tile covering the entire +area of rendering target. The default origin is TPoint(0,0). + +@see CDirectGdiContext::SetBrushPattern() + +@param aOrigin An origin point for the brush. The coordinates are relative + to the rectangle to fill, i.e. specify TPoint(0,0) to align the pattern flush with + the top and left hand sides of the rectangle. + +@pre None. +@post New brush origin will be used when filling an area with a pattern is used on + subsequent drawing operations. It remains in effect until another SetBrushOrigin() + with a different parameter is called. +*/ +EXPORT_C void CDirectGdiContext::SetBrushOrigin(const TPoint& aOrigin) + { + GRAPHICS_TRACE2("CDirectGdiContext::SetBrushOrigin(%d,%d)", aOrigin.iX, aOrigin.iY); + if (aOrigin != iBrushOrigin) + { + iBrushOrigin = aOrigin; + iEngine->SetBrushOrigin(iBrushOrigin); + } + } + + +/** +Sets the brush style used when filling the area of shapes and the background of text boxes. +Use ENullBrush to draw the outline of a fillable shape on its own, without filling. + +The error state is set to KErrArgument if aBrushStyle is an invalid brush style. + +@see DirectGdi::TBrushStyle + +@param aBrushStyle The brush style to set. + +@pre If aBrushStyle is EPatternedBrush, a pattern must have been set first using SetBrushPattern(). +@post New brush style will be used for subsequent drawing operations, and remains in effect + until another SetBrushStyle() with a different parameter is called. +@panic DGDI 9, if aBrushStyle is EPatternedBrush but no brush pattern has successfully been set. +*/ +EXPORT_C void CDirectGdiContext::SetBrushStyle(DirectGdi::TBrushStyle aBrushStyle) + { + GRAPHICS_TRACE1("CDirectGdiContext::SetBrushStyle(%d)", aBrushStyle); + if (aBrushStyle < DirectGdi::ENullBrush || aBrushStyle > DirectGdi::EDiamondCrossHatchBrush) + { + iDriver.SetError(KErrArgument); + return; + } + + if (aBrushStyle != iBrushStyle) + { + GRAPHICS_ASSERT_ALWAYS(aBrushStyle != DirectGdi::EPatternedBrush || iBrushPatternUsed, EDirectGdiPanicBrushPatternNotSet); + iBrushStyle = aBrushStyle; + iEngine->SetBrushStyle(iBrushStyle); + } + } + + +/** +Sets a clipping region which will be used to clip subsequent rendering operations on the current target. +This operation is non-additive, any previous clipping region setting is replaced by the new one. A clipping +region can contain one or more rectangles and is specified in absolute values in the target coordinate system. +By default (when a target is activated for the first time) no clipping region is set and any drawing +operations will be clipped automatically to the full area of the rendering target. + +In the event of a failure, the error state is set to KErrArgument if the given region is invalid or not +fully contained within the area of target, otherwise one of the system-wide error codes. + +@see CDirectGdiContext::ResetClippingRegion() + +@param aRegion The new clipping region. + +@pre Region is not empty and is fully contained within the full area of the target. +@post Subsequent rendering operations will be clipped to the given region if there is no error + while performing the operation, otherwise previous clipping region settings will be retained. +*/ +EXPORT_C void CDirectGdiContext::SetClippingRegion(const TRegion& aRegion) + { + GRAPHICS_TRACE("CDirectGdiContext::SetClippingRegion"); + if (aRegion.CheckError()) + { + iDriver.SetError(KErrArgument); + return; + } + iClippingRegion.Copy(aRegion); + if (iClippingRegion.CheckError()) + { + iDriver.SetError(KErrNoMemory); + return; + } + iEngine->SetClippingRegion(iClippingRegion); + } + + +/** +Sets the drawing mode which will affect the way pen and brush colour are used in rendering operations. +The default drawing mode is EDrawModePEN. + +The error state is set to KErrArgument if aDrawMode is an invalid draw mode. + +@see DirectGdi::TDrawMode + +@param aDrawMode The drawing mode. + +@pre None. +@post The new drawing mode will be applied to subsequent rendering operations, and remains in effect + until another SetDrawMode() with a different parameter is called. +*/ +EXPORT_C void CDirectGdiContext::SetDrawMode(DirectGdi::TDrawMode aDrawMode) + { + GRAPHICS_TRACE1("CDirectGdiContext::SetDrawMode(%d)", aDrawMode); + if (aDrawMode != DirectGdi::EDrawModePEN && aDrawMode != DirectGdi::EDrawModeWriteAlpha) + { + iDriver.SetError(KErrArgument); + return; + } + + if (iDrawMode != aDrawMode) + { + iDrawMode = aDrawMode; + iEngine->SetDrawMode(iDrawMode); + } + } + + +/** +Sets the origin of the drawing engine coordinate system. By default this is TPoint(0,0) and +coincides with the origin of the target coordinate system which is at the top-left corner of +the full area of target. The X value increases from left to right, and Y value increases from +top to bottom. Integer values are used to represent the position within the coordinate system. + +All drawing operations are done relative to the engine’s origin. However, the clipping region +is always specified in absolute coordinate values (using the target coordinate system) and is +not affected by changes to the drawing engine’s coordinate system origin. + +@param aPoint The new origin for the drawing engine’s coordinate system. + +@pre None. +@post The origin of the drawing engine’s coordinate system is moved to the given position. + All subsequent drawing operations will be done relative to the new origin. The new origin remains + in effect until SetOrigin() is called again with a different parameter. +*/ +EXPORT_C void CDirectGdiContext::SetOrigin(const TPoint& aPoint) + { + GRAPHICS_TRACE2("CDirectGdiContext::SetOrigin(%d,%d)", aPoint.iX, aPoint.iY); + if (aPoint != iOrigin) + { + iOrigin = aPoint; + iEngine->SetOrigin(iOrigin); + } + } + + +/** +Sets the colour that will be used for drawing lines, outlines of filled shapes and text. The +default pen colour is black. For outline and shadow fonts the alpha value of the pen colour will be +used for blending the font to the destination. + +@see CDirectGdiContext::Plot() +@see CDirectGdiContext::DrawLine() +@see CDirectGdiContext::DrawRoundRect() +@see CDirectGdiContext::DrawRect() +@see CDirectGdiContext::DrawPolyLine() +@see CDirectGdiContext::DrawPolyLineNoEndPoint() +@see CDirectGdiContext::DrawPolygon() +@see CDirectGdiContext::DrawPie() +@see CDirectGdiContext::DrawArc() +@see CDirectGdiContext::DrawText() + +@param aColor The pen colour. + +@pre None. +@post The new pen colour will be used for subsequent drawing of lines, outlines of filled shapes and text. + The new pen colour remains in effect until another SetPenColor() with a different parameter is called. +*/ +EXPORT_C void CDirectGdiContext::SetPenColor(const TRgb& aColor) + { + GRAPHICS_TRACE1("CDirectGdiContext::SetPenColor(%d)", aColor.Internal()); + if (aColor != iPenColor) + { + iPenColor = aColor; + iEngine->SetPenColor(iPenColor); + } + } + + +/** +Sets the pen or line drawing style. + +The pen style is used to draw lines and outlines of shapes. ENullPen can be used if border or +outlines are not required (when drawing a filled shape). The default pen style is ESolidPen. + +The error state is set to KErrArgument if aPenStyle is an invalid pen style. + +@see CDirectGdiContext::Plot() +@see CDirectGdiContext::DrawLine() +@see CDirectGdiContext::DrawRoundRect() +@see CDirectGdiContext::DrawRect() +@see CDirectGdiContext::DrawPolyLine() +@see CDirectGdiContext::DrawPolyLineNoEndPoint() +@see CDirectGdiContext::DrawPolygon() +@see CDirectGdiContext::DrawPie() +@see CDirectGdiContext::DrawArc() +@see DirectGdi::TPenStyle + +@param aPenStyle The pen style. + +@pre None. +@post The new pen style will be applied for subsequent drawing lines and outlines of filled shapes. + The new pen style remains in effect until another SetPenStyle() with a different parameter is called. +*/ +EXPORT_C void CDirectGdiContext::SetPenStyle(DirectGdi::TPenStyle aPenStyle) + { + GRAPHICS_TRACE1("CDirectGdiContext::SetPenStyle(%d)", aPenStyle); + if (aPenStyle < DirectGdi::ENullPen || aPenStyle > DirectGdi::EDotDotDashPen) + { + iDriver.SetError(KErrArgument); + return; + } + + if (aPenStyle != iPenStyle) + { + iPenStyle = aPenStyle; + iEngine->SetPenStyle(iPenStyle); + } + } + + +/** +Sets the pen size for drawing lines or the outlines of a filled shape. The default pen size is 1. +Lines with pen size greater than 1 are drawn with rounded ends that extend beyond the end points +and are always drawn using EDrawModePEN for compatibility reasons. + +The error state is set to KErrArgument if the specified width or height is negative. + +@see CDirectGdiContext::Plot() +@see CDirectGdiContext::DrawLine() +@see CDirectGdiContext::DrawRoundRect() +@see CDirectGdiContext::DrawRect() +@see CDirectGdiContext::DrawPolyLine() +@see CDirectGdiContext::DrawPolyLineNoEndPoint() +@see CDirectGdiContext::DrawPolygon() +@see CDirectGdiContext::DrawPie() +@see CDirectGdiContext::DrawArc() + +@param aSize The pen size. + +@pre None. +@post The new pen size is used for subsequent drawing lines and outlines of filled shapes. The new + pen size remains in effect until another SetPenSize() with a different parameter is called. +*/ +EXPORT_C void CDirectGdiContext::SetPenSize(const TSize& aSize) + { + GRAPHICS_TRACE2("CDirectGdiContext::SetPenSize(%d,%d)", aSize.iWidth, aSize.iHeight); + if ((aSize.iWidth < 0) || (aSize.iHeight < 0)) + { + iDriver.SetError(KErrArgument); + return; + } + + if (aSize != iPenSize) + { + iPenSize = aSize; + iEngine->SetPenSize(iPenSize); + } + } + + +/** +Sets the colour that will be used for drawing the shadow for shadowed text. + +@param aColor The shadow colour. + +@pre None. +@post The new colour will be used for subsequent drawing of text which has a type EFourColourBlendGlyphBitmap. + The shadow component of the text will be filled with this colour. + The new pen colour remains in effect until another SetTextShadowColor() with a different parameter is called. +*/ +EXPORT_C void CDirectGdiContext::SetTextShadowColor(const TRgb& aColor) + { + GRAPHICS_TRACE1("CDirectGdiContext::SetTextShadowColor(%d)", aColor.Internal()); + if (aColor != iTextShadowColor) + { + iTextShadowColor = aColor; + iEngine->SetTextShadowColor(aColor); + } + } + + +/** +Sets the character justification. +The function provides a concrete implementation of the pure virtual function CGraphicsContext::SetCharJustification(). +The function behaviour is the same as documented (in detail) in that class. + +@param aExcessWidth The excess width (in pixels) to be distributed between the specified number of characters. +@param aNumChars The number of characters involved. + +@see CGraphicsContext::SetCharJustification() +*/ +EXPORT_C void CDirectGdiContext::SetCharJustification(TInt aExcessWidth, TInt aNumChars) + { + GRAPHICS_TRACE2("CDirectGdiContext::SetCharJustification(%d,%d)", aExcessWidth, aNumChars); + if (aExcessWidth == 0 || aNumChars <= 0) + { + iCharJustExcess = 0; + iCharJustNum = 0; + } + else + { + iCharJustExcess = aExcessWidth; + iCharJustNum = aNumChars; + } + } + + +/** +Sets the word justification. +The function provides a concrete implementation of the pure virtual function CGraphicsContext::SetWordJustification(). +The function behaviour is the same as documented (in detail) in that class. + +@param aExcessWidth The width (in pixels) to be distributed between the specified number of spaces. + It may be positive, in which case the text is stretched, or negative, in which case it is shrunk. +@param aNumGaps The number of word spaces (characters with the code U+0020) over which the change in width is distributed. + +@see CGraphicsContext::SetWordJustification() +*/ +EXPORT_C void CDirectGdiContext::SetWordJustification(TInt aExcessWidth, TInt aNumGaps) + { + GRAPHICS_TRACE2("CDirectGdiContext::SetWordJustification(%d,%d)", aExcessWidth, aNumGaps); + if (aExcessWidth <= 0 || aNumGaps <= 0) + { + iWordJustExcess = 0; + iWordJustNum = 0; + } + else + { + iWordJustExcess = aExcessWidth; + iWordJustNum = aNumGaps; + } + } + + +/** +Sets the underline style for all subsequently drawn text. +The function provides a concrete implementation of the pure virtual function CGraphicsContext::SetUnderlineStyle(). +The function behaviour is the same as documented in that class. + +@param aUnderlineStyle The underline style to be used. + +@see CGraphicsContext::SetUnderlineStyle() +*/ +EXPORT_C void CDirectGdiContext::SetUnderlineStyle(DirectGdi::TFontUnderline aUnderlineStyle) + { + GRAPHICS_TRACE1("CDirectGdiContext::SetWordJustification(%d)", aUnderlineStyle); + iUnderline = aUnderlineStyle; + } + + +/** +Sets the strikethrough style for all subsequently drawn text. +The function provides a concrete implementation of the pure virtual function CGraphicsContext::SetStrikethroughStyle(). +The function behaviour is the same as documented in that class. + +@param aStrikethroughStyle The strikethrough style to be used. + +@see CGraphicsContext::SetStrikethroughStyle() +*/ +EXPORT_C void CDirectGdiContext::SetStrikethroughStyle(DirectGdi::TFontStrikethrough aStrikethroughStyle) + { + GRAPHICS_TRACE1("CDirectGdiContext::SetStrikethroughStyle(%d)", aStrikethroughStyle); + iStrikethrough = aStrikethroughStyle; + } + + +/** +Sets the bitmap to be used as the brush pattern when EPatternedBrush is selected. +The DirectGDI generic layer owns the bitmap and will keep the bitmap until ResetBrushPattern() is called. + +The client may modify the content of the bitmap used as the brush pattern. If this is done after +issuing drawing commands there is no guarantee which bitmap content will be used as brush pattern. +Clients must call Finish() on the driver before modifying the bitmap content if they want a guaranteed +result that the previously issued drawing commands will be drawn using the old bitmap brush pattern. + +In the event of a failure, the error state is set to KErrCouldNotConnect if no connection to the font +and bitmap server could be made, KErrBadHandle if the handle of the bitmap is null, KErrUnknown if +no bitmap could be found with the specified handle number, otherwise one of the system-wide error codes. + +@see CDirectGdiContext::SetBrushStyle() +@see CDirectGdiContext::SetBrushOrigin() +@see CDirectGdiContext::ResetBrushPattern() + +@param aBitmap Bitmap that will be used as the brush pattern. + +@pre Bitmap is fully constructed. +@post Bitmap will be used as the brush pattern for subsequent drawing operations when EPatternedBrush + is selected. It remains in effect until ResetBrushPattern() is called. +*/ +EXPORT_C void CDirectGdiContext::SetBrushPattern(const CFbsBitmap& aBitmap) + { + GRAPHICS_TRACE1("CDirectGdiContext::SetBrushPattern(%d)", aBitmap.Handle()); + SetBrushPattern(aBitmap.Handle()); + } + + +/** +Sets the bitmap to be used as the brush pattern when EPatternedBrush is selected. +The DirectGDI generic layer owns the bitmap and will keep the bitmap until ResetBrushPattern() is called. +If the client modifies the content of the bitmap used as the brush pattern after issuing any drawing +commands that uses that brush pattern, the method does not guarantee whether the old bitmap +content or the new one will be used as brush pattern. Clients must call Finish() on the driver +before modifying the bitmap content if they want a guaranteed result that the previously issued +drawing commands will be drawn using the old bitmap brush pattern. + +In the event of a failure, the error state is set to KErrCouldNotConnect if no connection to the font +and bitmap server could be made, KErrBadHandle if the handle is null, KErrUnknown if no bitmap could +be found with the specified handle number, otherwise one of the system-wide error codes. + +@param aFbsBitmapHandle Bitmap handle that will be used as the brush pattern. + +@pre Bitmap belonging to the handle is fully constructed. +@post Bitmap will be used as the brush pattern for subsequent drawing operations when EPatternedBrush + is selected. It remains in effect until ResetBrushPattern() is called. +@panic DGDI 8, if aFbsBitmapHandle is 0. +*/ +EXPORT_C void CDirectGdiContext::SetBrushPattern(TInt aFbsBitmapHandle) + { + GRAPHICS_TRACE1("CDirectGdiContext::SetBrushPattern(%d)", aFbsBitmapHandle); + if (aFbsBitmapHandle == KNullHandle) + { + iDriver.SetError(KErrBadHandle); + return; + } + + // Check we're not already using the passed brush pattern + if (iBrushPattern.Handle() == aFbsBitmapHandle) + { + return; + } + + // Delete any previously saved brush pattern + CleanUpBrushPattern(); + + TInt result = iBrushPattern.Duplicate(aFbsBitmapHandle); + if (result == KErrNone) + { + result = iEngine->SetBrushPattern(iBrushPattern); + } + + if (result == KErrNone) + { + iBrushPatternUsed = ETrue; + } + else + { + iDriver.SetError(result); + } + + return; + } + + +/** +Selects the font to be used for text drawing. +Notes: +When the font is no longer required, use ResetFont() to free up the memory used. +If SetFont() is used again without using ResetFont() then the previous font is reset +automatically. If no font has been selected, and an attempt is made to draw text with +DrawText(), then a panic occurs. + +@see CDirectGdiContext::ResetFont() +@see CDirectGdiContext::DrawText() + +@param aFont The font to be used. + +@panic DGDI 12, if aFont has an invalid handle or is not a CFbsFont, or the font cannot be duplicated. +*/ +EXPORT_C void CDirectGdiContext::SetFont(const CFont* aFont) + { + GRAPHICS_TRACE("CDirectGdiContext::SetFont"); + // Note: We pass a ptr in, rather than a reference, because otherwise the caller would almost always have to do complex casting + GRAPHICS_ASSERT_ALWAYS(aFont->TypeUid() == KCFbsFontUid, EDirectGdiPanicInvalidFont); + const CDirectGdiFont* font = reinterpret_cast(aFont); + GRAPHICS_ASSERT_ALWAYS(font->Handle(), EDirectGdiPanicInvalidFont); + + if (iFont.Handle() == font->Handle()) + { + return; + } + ResetFont(); + TInt err = iFont.Duplicate(font->Handle()); + GRAPHICS_ASSERT_ALWAYS(err == KErrNone, EDirectGdiPanicInvalidFont); // This may seem extreme but it is what BitGdi did + iEngine->SetFont(iFont.Address()->UniqueFontId()); + } + + +/** +Copies the content of a rectangular area on the target to another location. +The source rect will be intersected with the target’s full extent. + +@param aOffset Offset from the top left corner of the rectangle to be copied to the top left corner of the copy. +@param aRect Area to be copied. + +@pre The rendering target has been activated. +@post Request to copy an area has been accepted. There is no guarantee that the + request has been processed when this method returns. + +@panic DGDI 7, if the rendering context has not been activated. +*/ +EXPORT_C void CDirectGdiContext::CopyRect(const TPoint& aOffset, const TRect& aRect) + { + GRAPHICS_TRACE("CDirectGdiContext::CopyRect"); + if (aRect.IsEmpty() || aOffset == TPoint(0,0)) + { + return; + } + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + iEngine->CopyRect(aOffset, aRect); + } + +/** +Copies all settings from the specified DirectGDI context. + +@param aGc The DirectGDI context whose settings are to be copied. +*/ +EXPORT_C void CDirectGdiContext::CopySettings(const CDirectGdiContext& aGc) + { + GRAPHICS_TRACE("CDirectGdiContext::CopySettings"); + SetOrigin(aGc.iOrigin); + SetFont(&(aGc.iFont)); + SetCharJustification(aGc.iCharJustExcess, aGc.iCharJustNum); + SetWordJustification(aGc.iWordJustExcess, aGc.iWordJustNum); + iLastPrintPosition = aGc.iLastPrintPosition; + SetStrikethroughStyle(aGc.iStrikethrough); + SetUnderlineStyle(aGc.iUnderline); + SetPenColor(aGc.iPenColor); + SetPenSize(aGc.iPenSize); + SetPenStyle(aGc.iPenStyle); + SetDrawMode(aGc.iDrawMode); + SetTextShadowColor(aGc.iTextShadowColor); + SetBrushColor(aGc.iBrushColor); + SetBrushStyle(aGc.iBrushStyle); + if(aGc.iBrushPattern.Handle()) + { + SetBrushPattern(aGc.iBrushPattern.Handle()); + } + iBrushPatternUsed = aGc.iBrushPatternUsed; + SetBrushOrigin(aGc.iBrushOrigin); + } + +/** +Updates the justification settings. +This function assumes that NoJustifyAutoUpdate() has not been used. + +@param aText The text for which justification is to be adjusted. +@param aParam Parameters used in drawing text. + +@panic DGDI 7, if the rendering context has not been activated. +@panic DGDI 13, if NoJustifyAutoUpdate() had been called prior to this. +*/ +EXPORT_C void CDirectGdiContext::UpdateJustification(const TDesC& aText, const DirectGdi::TTextParameters* aParam) + { + GRAPHICS_TRACE("CDirectGdiContext::UpdateJustification"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + GRAPHICS_ASSERT_ALWAYS(iAutoUpdateJustification, EDirectGdiPanicAutoUpdateJustificationUsed); + if (((iCharJustNum < 1) || (iCharJustExcess == 0)) && ((iWordJustNum < 1) || (iWordJustExcess < 1))) + { + return; + } + + TInt length = aText.Length(); + CFont::TPositionParam param; + param.iText.Set(aText); // Set the start of the string + if (aParam) + { + length = aParam->iEnd; + param.iPosInText = aParam->iStart; + } + TInt excess = 0; + TInt glyphs = 0; + RShapeInfo shapeInfo; + for (TInt count = 0; count < length; count++) + { + if ((iCharJustNum > 0) && (iCharJustExcess != 0)) + { + excess += CGraphicsContext::JustificationInPixels(iCharJustExcess, iCharJustNum); + } + if ((iWordJustNum > 0) && (iWordJustExcess > 0) && (aText[count] == ' ')) + { + excess += CGraphicsContext::JustificationInPixels(iWordJustExcess, iWordJustNum); + } + if (iCharJustNum < (glyphs + length - count)) // there's at least 1 combined glyph to come + { + // otherwise we can skip this slow bit and just increment + if (iFont.GetCharacterPosition2(param, shapeInfo)) + { + count = param.iPosInText - 1; // -1 'cos it gets incremented anyway + } + } + glyphs++; + } + if (shapeInfo.IsOpen()) + { + shapeInfo.Close(); + } + iLastPrintPosition.iX += excess; + } + + +/** +Updates the justification for vertical text. +This function assumes that NoJustifyAutoUpdate() has not been used. + +@param aText The text for which justification is to be adjusted. +@param aParam Parameters used in drawing text. +@param aUp ETrue, if text is to be justified upwards; EFalse, if text is to be justified downwards. + +@panic DGDI 7, if the rendering context has not been activated. +@panic DGDI 13, if NoJustifyAutoUpdate() had been called prior to this. +*/ +EXPORT_C void CDirectGdiContext::UpdateJustificationVertical(const TDesC& aText, const DirectGdi::TTextParameters* aParam, TBool aUp) + { + GRAPHICS_TRACE("CDirectGdiContext::UpdateJustificationVertical"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + GRAPHICS_ASSERT_ALWAYS(iAutoUpdateJustification, EDirectGdiPanicAutoUpdateJustificationUsed); + + if (((iCharJustNum < 1) || (iCharJustExcess == 0)) && ((iWordJustNum < 1) || (iWordJustExcess < 1))) + { + return; + } + + TInt length = aText.Length(); + CFont::TPositionParam param; + param.iText.Set(aText); // Set the start of the string + if (aParam) + { + length = aParam->iEnd; + param.iPosInText = aParam->iStart; + } + TInt excess = 0; + TInt glyphs = 0; + RShapeInfo shapeInfo; + for (TInt count = 0; count < length; count++) + { + if ((iCharJustNum > 0) && (iCharJustExcess != 0)) + { + excess += CGraphicsContext::JustificationInPixels(iCharJustExcess, iCharJustNum); + } + if ((iWordJustNum > 0) && (iWordJustExcess > 0) && (aText[count] == ' ')) + { + excess += CGraphicsContext::JustificationInPixels(iWordJustExcess, iWordJustNum); + } + if (iCharJustNum < (glyphs + length - count)) // there's at least 1 combined glyph to come + { + // otherwise we can skip this slow bit and just increment + if (iFont.GetCharacterPosition2(param, shapeInfo)) + { + count = param.iPosInText - 1; // -1 because it gets incremented anyway + } + } + glyphs++; + } + if (shapeInfo.IsOpen()) + { + shapeInfo.Close(); + } + + if (aUp) + { + iLastPrintPosition.iY -= excess; + } + else + { + iLastPrintPosition.iY += excess; + } + } + + +/** +Selects a font for text drawing but does not take a copy. +The original must not be destroyed until SetFont(), SetFontNoDuplicate(), ResetFont() +or the destructor is called. + +@param aFont A pointer to the font to be used. +@panic DGDI 12, if aFont has no handle or is not a CFbsFont. +*/ +EXPORT_C void CDirectGdiContext::SetFontNoDuplicate(const CDirectGdiFont* aFont) + { + GRAPHICS_TRACE("CDirectGdiContext::SetFontNoDuplicate"); + // Note: We pass a ptr in, rather than a reference, because otherwise the caller would almost always have to do complex casting + GRAPHICS_ASSERT_ALWAYS(aFont->TypeUid() == KCFbsFontUid, EDirectGdiPanicInvalidFont); + GRAPHICS_ASSERT_ALWAYS(aFont->Handle(), EDirectGdiPanicInvalidFont); + + if (iFont.Handle() == aFont->Handle()) + { + return; + } + + ResetFont(); + iFont = *aFont; + iEngine->SetFont(iFont.Address()->UniqueFontId()); + } + + +/** +Checks to see if a brush pattern is currently set. + +@return ETrue is a brush pattern is currently set, EFalse if no brush pattern is currently set. +*/ +EXPORT_C TBool CDirectGdiContext::HasBrushPattern() const + { + GRAPHICS_TRACE("CDirectGdiContext::HasBrushPattern"); + return iBrushPatternUsed; + } + + +/** +Tests whether a font is used. + +@return ETrue, if a font is being used; EFalse, otherwise. +*/ +EXPORT_C TBool CDirectGdiContext::HasFont() const + { + GRAPHICS_TRACE("CDirectGdiContext::HasFont"); + TBool result = EFalse; + if (iFont.Handle() != KNullHandle) + result = ETrue; + return result; + } + + +/** +Externalises the context and the drawing engine object to the write stream. +It is important that the font and brush bitmap of the GC is maintained between +calls to ExternalizeL() and InternalizeL(). The font handle and brush bitmap handle +is externalised, not the underlying data. This is done for performance reasons. + +@param aWriteStream Write stream. + +@pre None. +@post The context and drawing engine object states are written to the write stream. + +@see MDirectGdiEngine::InternalizeL +@leave If there was an error writing to the write stream. +*/ +EXPORT_C void CDirectGdiContext::ExternalizeL(RWriteStream& aWriteStream) + { + GRAPHICS_TRACE("CDirectGdiContext::ExternalizeL"); + aWriteStream << KDirectGDIContext_VerNo; + iEngine->ExternalizeL(aWriteStream); + + aWriteStream << iOrigin; + aWriteStream.WriteInt32L(iFont.Handle()); + aWriteStream.WriteInt32L(iCharJustExcess); + aWriteStream.WriteInt32L(iCharJustNum); + aWriteStream.WriteInt32L(iWordJustExcess); + aWriteStream.WriteInt32L(iWordJustNum); + aWriteStream << iLastPrintPosition; + aWriteStream.WriteUint8L(iStrikethrough); + aWriteStream.WriteUint8L(iUnderline); + aWriteStream << iPenColor; + aWriteStream.WriteUint32L(iPenSize.iWidth); + aWriteStream.WriteUint32L(iPenSize.iHeight); + aWriteStream.WriteUint8L(iPenStyle); + aWriteStream.WriteUint8L(iDrawMode); + aWriteStream << iTextShadowColor; + aWriteStream << iBrushColor; + aWriteStream.WriteInt32L(iBrushPattern.Handle()); + aWriteStream.WriteUint8L(iBrushStyle); + aWriteStream.WriteUint8L(iBrushPatternUsed); + aWriteStream << iBrushOrigin; + aWriteStream.WriteUint8L(iAutoUpdateJustification); + } + + +/** +Internalises the context and the drawing engine object from the read stream. +It is important that the font and brush bitmap of the GC is maintained between +calls to ExternalizeL() and InternalizeL(). The font handle and brush bitmap handle +is externalised, not the underlying data. This is done for performance reasons. + +@param aReadStream Read stream. + +@pre The font has not been released since the last call of CDirectGdiContext::ExternalizeL on the stream +@pre The handle of the brush pattern bitmap has not been closed since the call to CDirectGdiContext::ExternalizeL on the stream. +@post The context and drawing engine object states are updated with the values from the read stream. + +@see MDirectGdiEngine::ExternalizeL +@leave If there was an error reading from the read stream. +*/ +EXPORT_C void CDirectGdiContext::InternalizeL(RReadStream& aReadStream) + { + GRAPHICS_TRACE("CDirectGdiContext::InternalizeL"); + TUint16 archiveVerNo = 0; + aReadStream >> archiveVerNo; + iEngine->InternalizeL(aReadStream); + + TPoint origin; + aReadStream >> origin; + SetOrigin(origin); + ResetFont(); + TInt fontHandle = aReadStream.ReadInt32L(); + if(fontHandle) + { + TInt res = iFont.Duplicate(fontHandle); + if(res == KErrNone) + { + iEngine->SetFont(iFont.Address()->UniqueFontId()); + } + else + { + iDriver.SetError(res); + } + } + iCharJustExcess = aReadStream.ReadUint32L(); + iCharJustNum = aReadStream.ReadUint32L(); + iWordJustExcess = aReadStream.ReadUint32L(); + iWordJustNum = aReadStream.ReadUint32L(); + aReadStream >> iLastPrintPosition; + iStrikethrough = (DirectGdi::TFontStrikethrough)aReadStream.ReadUint8L(); + iUnderline = (DirectGdi::TFontUnderline)aReadStream.ReadUint8L(); + TRgb penColor; + aReadStream >> penColor; + SetPenColor(penColor); + TSize penSize; + penSize.iWidth = aReadStream.ReadUint32L(); + penSize.iHeight = aReadStream.ReadUint32L(); + SetPenSize(penSize); + DirectGdi::TPenStyle penStyle = (DirectGdi::TPenStyle)aReadStream.ReadUint8L(); + SetPenStyle(penStyle); + DirectGdi::TDrawMode drawMode = (DirectGdi::TDrawMode)aReadStream.ReadUint8L(); + SetDrawMode(drawMode); + TRgb textShadowColor; + aReadStream >> textShadowColor; + SetTextShadowColor(textShadowColor); + TRgb brushColor; + aReadStream >> brushColor; + SetBrushColor(brushColor); + TInt patternHandle = aReadStream.ReadInt32L(); + if (patternHandle) + { + // Brush pattern must be set before style, otherwise there'll be a panic! + SetBrushPattern(patternHandle); + } + DirectGdi::TBrushStyle brushStyle; + brushStyle = (DirectGdi::TBrushStyle)aReadStream.ReadInt8L(); + SetBrushStyle(brushStyle); + iBrushPatternUsed = (TBool)aReadStream.ReadUint8L(); + TPoint brushOrigin; + aReadStream >> brushOrigin; + SetBrushOrigin(brushOrigin); + iAutoUpdateJustification = (TBool)aReadStream.ReadUint8L(); + } + + +/** +Retrieves the currently set brush colour. + +@return The current brush colour. +*/ +EXPORT_C TRgb CDirectGdiContext::BrushColor() const + { + return iBrushColor; + } + + +/** +Retrieves the currently set pen colour. + +@return The current pen colour. +*/ +EXPORT_C TRgb CDirectGdiContext::PenColor() const + { + return iPenColor; + } + +/** +Retrieves the currently set text shadow colour. + +@return The current text shadow colour. +*/ +EXPORT_C TRgb CDirectGdiContext::TextShadowColor() const + { + return iTextShadowColor; + } + +/** +Draws an image based resource which may be generated using non-native rendering API such as OpenGL ES +or OpenVG. The resource will be drawn at the specified position in its original size with orientation +according to the specified rotation parameter. The current clipping region applies. The resource can be +drawn rotated using the DirectGdi::TGraphicsRotation enum which defines possible rotation values in +clockwise degrees. + +In the event of a failure, the error state is set to one of the system-wide error codes. + +@param aPos The position of the top-left corner of the resource. +@param aSource The resource to be drawn. +@param aRotation The rotation to be applied to the resource before it is drawn. The default value is DirectGdi::EGraphicsRotationNone. + +@pre Drawing context has been activated on a rendering target. The resource has been fully constructed. +@post Request to draw resource has been accepted. There is no guarantee that the request has been completed + when this method returns. + +@panic DGDI 7, if the rendering context has not been activated. +*/ +EXPORT_C void CDirectGdiContext::DrawResource( + const TPoint& aPos, + const RDirectGdiDrawableSource& aSource, + DirectGdi::TGraphicsRotation aRotation) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawResource"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + + if (aSource.Handle() != KNullHandle) + { + iEngine->DrawResource(aPos, aSource, aRotation); + } + else + { + iDriver.SetError(KErrBadHandle); + } + } + +/** +Draws an image based resource. The resource will be rendered to the given destination rectangle on +rendering target in its original dimensions with orientation according to the specified rotation parameter. +Drawing will be clipped to the given destination rectangle. The current clipping region applies. + +In the event of a failure, the error state is set to one of the system-wide error codes. + +@param aDestRect Destination rectangle to which the resource will be rendered. +@param aSource The resource to be drawn. +@param aRotation Rotation to be applied to the resource before it is drawn. Default value is DirectGdi::EGraphicsRotationNone. + +@pre Drawing context has been activated on a rendering target. The resource has been fully constructed. +@post Request to draw resource has been accepted. There is no guarantee that the request has been completed + when this method returns. + +@panic DGDI 7, if the rendering context has not been activated. +*/ +EXPORT_C void CDirectGdiContext::DrawResource(const TRect& aDestRect, + const RDirectGdiDrawableSource& aSource, + DirectGdi::TGraphicsRotation aRotation) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawResource"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + + if (aSource.Handle() != KNullHandle) + { + if ((aDestRect.Width() > 0) && (aDestRect.Height() > 0)) + { + iEngine->DrawResource(aDestRect, aSource, aRotation); + } + } + else + { + iDriver.SetError(KErrBadHandle); + } + } + + +/** +Draws an image based resource. The resource is rendered into the given destination rectangle. +Scaling (stretching or compression) applies if the destination rectangle is different from the +source rectangle. The resource orientation is set based on the specified rotation parameter +before scaling and drawing operations are performed. + +If the user modifies the content of the resource after issuing a DrawResource() command (from the +same thread), the adaptation must make sure that the user’s operations are serialised within +that thread, for example, DrawResource() is processed before the modify operations. The adaptation +does not guarantee the result if the resource modification is performed from threads other than +the one that issued the DrawResource() command. To achieve a guaranteed result in that case, users +must perform synchronisation between any threads that operate on the resource and issue Finish() +on the driver whenever necessary. When using other renderers or mappings, synchronisation is needed +even when this is from within the same thread. + +In the event of a failure, the error state is set to one of the system-wide error codes. + +@param aDestRect The destination rectangle to which the resource will be rendered. +@param aSource The resource to draw. +@param aSrcRect The source rectangle specifying the area/sub-area of the resource to be rendered. +@param aRotation Rotation to be applied to the resource before it is drawn + +@pre The rendering target has been activated. The resource has been fully constructed. +@post Request to draw an image based resource has been accepted. There is no guarantee that the + request has been completed when this method returns. + +@panic DGDI 7, if the rendering context has not been activated. +*/ +EXPORT_C void CDirectGdiContext::DrawResource( + const TRect& aDestRect, + const RDirectGdiDrawableSource& aSource, + const TRect& aSrcRect, + DirectGdi::TGraphicsRotation aRotation) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawResource"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + + if (aSource.Handle() != KNullHandle) + { + if ((aDestRect.Width() > 0) && (aDestRect.Height() > 0) + && (aSrcRect.Width() > 0) && (aSrcRect.Height() > 0)) + { + iEngine->DrawResource(aDestRect, aSource, aSrcRect, aRotation); + } + } + else + { + iDriver.SetError(KErrBadHandle); + } + } + + +/** +Draws a non-image based resource. The resource will be rendered into the given destination rectangle. +The current clipping region applies. The adaptation is free to interpret the parameters and may define +their own rules on how to handle the rendering of a non-image based resource. + +In the event of a failure, the error state is set to one of the system-wide error codes. + +@param aDestRect The destination rectangle to which the resource will be rendered. +@param aSource The resource. +@param aParam Parameters specifying how to draw the resource. + +@pre The rendering target has been activated. The resource has been fully constructed. +@post Request to draw a non-image based resource has been accepted. + There is no guarantee that the request has been completed when this method returns. + +@panic DGDI 7, if the rendering context has not been activated. +*/ +EXPORT_C void CDirectGdiContext::DrawResource( + const TRect& aDestRect, + const RDirectGdiDrawableSource& aSource, + const TDesC8& aParam) + { + GRAPHICS_TRACE("CDirectGdiContext::DrawResource"); + GRAPHICS_ASSERT_ALWAYS(iActivated, EDirectGdiPanicContextNotActivated); + + if (aSource.Handle() != KNullHandle) + { + if ((aDestRect.Width() > 0) && (aDestRect.Height() > 0)) + { + iEngine->DrawResource(aDestRect, aSource, aParam); + } + } + else + { + iDriver.SetError(KErrBadHandle); + } + } + +/** +Retrieves a pointer to an instance of the appropriate extension interface implementation. + +@param aInterfaceId Interface identifier of the interface to be retrieved. +@param aInterface On return, holds the specified interface, or NULL if the interface cannot be found. + +@pre None. +@post None. + +@return KErrNone If the interface is supported, KErrNotSupported otherwise. + */ +EXPORT_C TInt CDirectGdiContext::GetInterface(TUid aInterfaceId, TAny*& aInterface) + { + GRAPHICS_TRACE("CDirectGdiContext::GetInterface"); + return iEngine->GetInterface(aInterfaceId, aInterface); + } + +/** +Release the brush pattern's handle, and mark it as no longer used. +*/ +void CDirectGdiContext::CleanUpBrushPattern() + { + iBrushPattern.Reset(); + iBrushPatternUsed = EFalse; + } + +/** +@internalTechnology + +Returns the baseline correction associated with this font. +This value is used to alter the underline/strikethrough position applied to linked fonts. + +@return The baseline correction value set by the rasterizer; or 0 if not set +*/ +TInt CDirectGdiContext::BaselineCorrection() + { + TOpenFontMetrics metrics; + if (iFont.GetFontMetrics(metrics)) + return metrics.BaselineCorrection(); + else + return 0; + }