Exemple #1
0
DocRect ArrowRec::FindBoundsAt(const DocCoord& ArrowCentre, const DocCoord& Direction, 
							   INT32 ParentLineWidth)
{
	DocRect Bounds(0,0,0,0);

	// Find a matrix to transform the ArrowHead to this Position.
	Trans2DMatrix Trans;
	GetArrowMatrix(ArrowCentre, Direction, ParentLineWidth, &Trans);

	// Note:
	// We should really be able to ask Gavin to Calculate the Bounds,
	// and pass him this Transform Matrix, but he can't do this at the
	// moment, so we'll have to actually transform the path into
	// a tempory path, and then ask him to calc the bounds of that.

	// Make a tempory path to transform
	Path* TransPath = new Path();
	if (TransPath == NULL)
		return Bounds;

	// Copy the path data from the ArrorHead into our tempory path.
	BOOL 	ok = TransPath->Initialise(ArrowShape->GetNumCoords());
	if (ok) ok = TransPath->CopyPathDataFrom(ArrowShape);

	if (!ok)
	{
		// Tidy up if we failed
		delete TransPath;
		return Bounds;
	}

	// Go transform the Tempory path
	Trans.Transform(TransPath->GetCoordArray(), 
					TransPath->GetNumCoords() );

	BOOL GDrawResult = FALSE;
	
	// Find out what the paths bounding rect is, taking into account
	// any bezier curve thingies. 

	GDrawContext *GD = GRenderRegion::GetStaticDrawContext();
	
	if (GD != NULL)
		GDrawResult = GD->CalcStrokeBBox((POINT*)TransPath->GetCoordArray(),
											TransPath->GetVerbArray(), TransPath->GetNumCoords(),
											(RECT *)(&Bounds),
											TRUE, 0, CAPS_ROUND, JOIN_ROUND, NULL) == 0;

	// If Gavin failed, then use backup technique of getting coord array bounds
	if (!GDrawResult)
		Bounds = TransPath->GetBoundingRect();

	// Delete the temporary transformed path
	delete TransPath;

	return Bounds;
}
Exemple #2
0
BOOL StringToBitmap::TTFAddString(String_256 *text, UINT32 Xsize, UINT32 Ysize, UINT32 DPI, PLOGFONT pLogFont,
                                  INT32 IntLeading, KernelBitmap **BM, UINT32 ForeColour)
{
    KernelBitmap *Bitmap = *BM;

    /*	HDC ScreenDC = CreateCompatibleDC(NULL);
    	if (ScreenDC == NULL)
    	{
    		ERROR3("StringToBitmap::AddString: Unable to create screen DC");
    		return FALSE;
    	}*/

    CDC SysDisplay;
    BOOL ok=SysDisplay.CreateCompatibleDC(NULL);
    if(!ok)
    {
        //DeleteDC(ScreenDC);
        ERROR3("StringToBitmap::TTF AddString: Unable to create CDC");
        return FALSE;
    }

    HDC ScreenDC = SysDisplay.m_hDC;

    // bodge to get things working with GetBezierFromChar
    INT32 OldlfHeight = pLogFont->lfHeight;
    pLogFont->lfHeight = -(pLogFont->lfHeight - IntLeading);

    UINT32 CurrentPathSizeAlloc = 0;
    Trans2DMatrix *pTransform = NULL;
    DocCoord *pPathCoords = NULL;

    Path *pPath = NULL;
    //pPath = new Path();

    DocCoord *pPolyCordBuffer = NULL;
    PathVerb *pPolyVerbBuffer = NULL;
    UINT32 TextLength = (UINT32)text->Length();
    SIZE StringSize= {0,0};

    // Get handle of font

//	HFONT hNewFont = CreateFontIndirect(pLogFont);
//	HGDIOBJ hOldFont = SelectObject(ScreenDC, hNewFont);

    CFont UnHintedCFont;
    if(!UnHintedCFont.CreateFontIndirect(pLogFont))
    {
        SysDisplay.DeleteDC();
        pLogFont->lfHeight = OldlfHeight;
        return FALSE;
    }

    CFont* pOldCFont=SysDisplay.SelectObject(&UnHintedCFont);

    // Get the default character to use if a charater is not present in the font.
    WCHAR FontDefaultCharacter = (unsigned char)'?';
    TEXTMETRIC FontTextData;
#ifdef _UNCCODE
    if (SysDisplay.GetTextMetrics(&FontTextData))
        FontDefaultCharacter = FontTextData.tmDefaultChar;
#else
    if (SysDisplay.GetTextMetrics(&FontTextData))
        FontDefaultCharacter = (unsigned char)FontTextData.tmDefaultChar;
#endif

    // Work out a nice scaling factor so the font fits in the bitmap ok...

    // Not 32 ?
    GetTextExtentPoint(ScreenDC, *text, TextLength, &StringSize);

    if(StringSize.cy == 0)
    {
        SysDisplay.SelectObject(pOldCFont);
        SysDisplay.DeleteDC();
        pLogFont->lfHeight = OldlfHeight;
        return FALSE;
    }

    //ERROR3IF(!ok, "Initial GetTextExtentPoint32() failed");
    double YScale = ((double)Ysize / (double)StringSize.cy) / (double)2;
    double XScale = YScale;

    // Shift thumbnail upwards, and scale down a bit - to get the g's looking right
    // One or two fonts require this reducing (their tops are clipped), 72000/100 is
    // about right for most of them though...
    // Note the external previews were done with 72000/220 for Matrix and 72000/140 for
    // the capital only fonts.
    double YShift = 72000/100;//72000/80;

    YScale = (YScale * 78) / 100;
    XScale = (XScale * 78) / 100;

    if(!text->IsEmpty())
    {
        const TCHAR* pCurrentChar = (const TCHAR*)(*text);

        while (ok && *pCurrentChar!=0)
        {
            // Get the current character as Unicode.
#ifdef _UNICODE
            WCHAR wchr = *pCurrentChar;		// pCurrentChar is a pointer to WCHAR in _UNICODE builds
#else
            UINT32 CharToConvert = 0;
            if (UnicodeManager::IsDBCSLeadByte(*pCurrentChar))
                CharToConvert = UnicodeManager::ComposeMultiBytes(*pCurrentChar, *(pCurrentChar+1));
            else
                CharToConvert = (unsigned char)(*pCurrentChar);
            WCHAR wchr = UnicodeManager::MultiByteToUnicode(CharToConvert);
#endif

            // Get positioning information for this character
            ok = GetTextExtentPoint(ScreenDC, *text, (pCurrentChar-(TCHAR*)(*text)), &StringSize);
            ERROR3IF(!ok, "GetTextExtentPoint32() failed");
            if (!ok) break;

            // Get the characters path
            DWORD PathSize = 0;
            ok = TextManager::GetBezierFromChar(&SysDisplay, wchr, pLogFont, &PathSize, (POINT *)NULL, (BYTE *)NULL);
            if (!ok)
            {
                wchr = FontDefaultCharacter;
                ok = TextManager::GetBezierFromChar(&SysDisplay, wchr, pLogFont, &PathSize, (POINT *)NULL, (BYTE *)NULL);
            }
            ERROR3IF(!ok, "GetBezierFromChar returned false");
            if (!ok) break;

            // Pointer to an array of path coordinates
            if(pPolyCordBuffer == NULL)
            {
                TRY
                {
                    pPolyCordBuffer = new DocCoord[PathSize];
                }
                CATCH (CMemoryException, e)
                {
                    pPolyCordBuffer = NULL;
                    /*ERROR(_R(IDS_OUT_OF_MEMORY), FALSE);*/
                }
                END_CATCH
            }

            // Pointer to an array of path verbs
            if(pPolyVerbBuffer == NULL)
            {
                TRY
                {
                    pPolyVerbBuffer = new PathVerb[PathSize];
                }
                CATCH (CMemoryException, e)
                {
                    pPolyVerbBuffer = NULL;
                    /*ERROR(_R(IDS_OUT_OF_MEMORY), FALSE);*/
                }
                END_CATCH
            }

            if (pPolyCordBuffer == NULL || pPolyVerbBuffer == NULL)
            {
                ok = FALSE;
                break;
            }

            CurrentPathSizeAlloc = PathSize;

            // Fill up the buffers until they're bursting with fontyness
            ok = TextManager::GetBezierFromChar(&SysDisplay, wchr, pLogFont, &PathSize, (POINT *)pPolyCordBuffer,
                                                (BYTE *)pPolyVerbBuffer);
            if(!ok) TRACEUSER( "Richard", _T("GetBezierFromChar returned false in second phase...\n"));
            if(!ok)	break;

            // Spaces set PathSize to zero
            if((PathSize > 0)/* && (pPath != NULL)*/)
            {
                pPath = new Path();
                pPath->Initialise(PathSize, 12);
                pPath->CopyPathDataFrom(pPolyCordBuffer, pPolyVerbBuffer, PathSize, TRUE);

                // Major bodge at present with the x spacing...
                Matrix scale(XScale, 0, 0, YScale, (INT32)((XScale*StringSize.cx*72000)/(double)DPI), (INT32)YShift);

                pTransform = new Trans2DMatrix(scale);
                pPathCoords = pPath->GetCoordArray();
                pTransform->Transform( pPathCoords, pPath->GetNumCoords() );
                delete pTransform;

                pPath->InitialiseFlags();

                ok = ALU->GradFillPath(pPath, ForeColour, ForeColour, 0, 0, 0,/*Xsize/2,*/ Ysize, S2BMP_ANTIALIAS);
                ERROR3IF(!ok, "Gradfillpath returned false");
                if(!ok)	break;

                delete pPath;
            }

            // S2BMP_MAGIC is the worderfully fabby constant that mark's getbezierfromchar returns
            // Theory goes that he's going to sort this out sometime...
            if(CurrentPathSizeAlloc != S2BMP_MAGIC)
            {
                delete []pPolyCordBuffer;
                delete []pPolyVerbBuffer;

                pPolyCordBuffer = NULL;
                pPolyVerbBuffer = NULL;
                CurrentPathSizeAlloc = 0;
            }

            pPath = NULL;
            pTransform = NULL;

            pCurrentChar = camStrinc(pCurrentChar);
        }
Exemple #3
0
/********************************************************************************************

>	BOOL BlendHelpers::BlendPaths(BlendNodeParam * pParam, Path * pPath)

	Author:		David_McClarnon (Xara Group Ltd) <*****@*****.**>
	Created:	21/2/2000
	Inputs:		The blend node parameter
	Outputs:	The blended path is stored in three arrays: the coords, the verbs, and the flags.
				The arrays are:
	
					pTempCoords
					pTempVerbs
					pTempFlags

					ArrayLength = the length of all three arrays

				This allows the caller to decide what to do with the blended path in a very flexible way.

	Returns:	TRUE if successful, FALSE otherwise
	Purpose:	Blends two BlendPath objects by the amount specified in BlendRatio
	SeeAlso:	-
********************************************************************************************/
BOOL BlendHelpers::BlendPaths(BlendNodeParam * pParam, Path * pPath)
{
	// Check entry params
	BlendPath * pBlendPathStart = pParam->GetStartBlendPath();
	BlendPath * pBlendPathEnd   = pParam->GetEndBlendPath();

	ERROR2IF(!pBlendPathStart->GetBlendNode()->IsNodePath(), FALSE,
		"Start blend path's node isn't a node path");

	ERROR2IF(!pBlendPathEnd->GetBlendNode()->IsNodePath(), FALSE,
		"End blend path's node isn't a node path");

	BOOL    ok = (pBlendPathStart != NULL && pBlendPathEnd != NULL);
 	if (ok) ok = (pBlendPathStart->GetBlendNode() != NULL && pBlendPathEnd->GetBlendNode() != NULL);
	ERROR3IF(!ok,"One or more NULL entry params");
	if (!ok) return FALSE;

	// Get the types of the two paths
	PathTypeEnum PathTypeStart = pBlendPathStart->GetPathType();
	PathTypeEnum PathTypeEnd   = pBlendPathEnd  ->GetPathType();
	
	// The blended path will be closed if either of the paths is a shape
	BOOL Closed = (PathTypeStart == PATHTYPE_SHAPE) || (PathTypeEnd == PATHTYPE_SHAPE);

	Path * pPathStart = NULL;

	// Find the paths associated with the start and end blend paths
	if (pBlendPathStart->GetBlendNode()->IsNodePath())
	{
		pPathStart = &(((NodePath *)pBlendPathStart->GetBlendNode())->InkPath);
	}

	Path * pPathEnd = NULL;

	if (pBlendPathEnd->GetBlendNode()->IsNodePath())
	{
		pPathEnd   = &(((NodePath *)pBlendPathEnd->GetBlendNode())->InkPath);
	}

	// Calculate how large the arrays have to be to store the blended path definition
	INT32 DestPathSize = ((pPathStart->GetNumCoords()+pPathEnd->GetNumCoords())*3)+500;

	// Get some arrays used to hold the blended path data, and error if any are NULL
	DocCoord*  	pDestCoords = GetCoordArray(DestPathSize);
	PathVerb*  	pDestVerbs  = GetVerbArray(DestPathSize);
	PathFlags* 	pDestFlags  = GetFlagArray(DestPathSize);
	UINT32* 		pBuff 		= GetGBlendBuff(DestPathSize);
	if (pDestCoords == NULL || pDestVerbs == NULL || pDestFlags == NULL || pBuff == NULL)
		return FALSE;

	// This section copes with the case when blending a line with a shape.
	// In this case we need to get a temp path the is actually a shape version of the line.
	// The line is simply reversed back onto itself to form a shape that would look identical to the 
	// line if rendered.  This allows the line to appear to open up to the shape when blended.
	Path Shape;
	if (PathTypeStart != PathTypeEnd)
	{
		BOOL ok = FALSE;
		if (!Shape.Initialise()) return FALSE;

		// if going from a line to a shape, convert the start path to a shape
		if (PathTypeStart == PATHTYPE_LINE && PathTypeEnd == PATHTYPE_SHAPE)
		{
			ok = NodeBlender::ConvertLineToShape(pPathStart,&Shape);
			pPathStart = &Shape;
		}

		// if going from a shape to a line, convert the end path to a shape
		if (PathTypeStart == PATHTYPE_SHAPE && PathTypeEnd == PATHTYPE_LINE)
		{
			ok = NodeBlender::ConvertLineToShape(pPathEnd,&Shape);
			pPathEnd = &Shape;
		}

		if (!ok) return FALSE;
	}

	// The blend should do a one-to-one mapping when the OneToOne flag is set AND both paths
	// have the same number of elements
	BOOL OneToOne = FALSE;
	if (pParam->GetOneToOne())
		OneToOne = (pBlendPathStart->GetNumElements() == pBlendPathEnd->GetNumElements());

	// Now actually blend the two paths

	GBlend GBlendObj;

	// Define the blend
	GBlendObj.Define(	(PPOINT)pPathStart->GetCoordArray(),	// Specify the start path
						pPathStart->GetVerbArray(),
						pPathStart->GetNumCoords(),

						(PPOINT)pPathEnd  ->GetCoordArray(),	// Specify the end path
						pPathEnd  ->GetVerbArray(),
						pPathEnd  ->GetNumCoords(),

						OneToOne,								// The one-to-one flag
						1024,								// Flatness

						pBuff,									// Buffer for GBlend to use
						DestPathSize*sizeof(UINT32));			// The buffer size

	// Blend the paths
	m_ArrayLength = GBlendObj.Blend(pParam->GetBlendRatio(),	// The blend ratio, 0.0 < BlendRatio < 1.0
									(PPOINT)pDestCoords,		// Array to store blended coords
									pDestVerbs,					// Array to store blended verbs
									DestPathSize);				// The num elements in the two arrays


	// If we're blending a line to another line, we need to make sure that the blended line
	// is going in a direction that corresponds to the source lines.  This ensures attributes
	// that depend on this direction (e.g. start and end arrows) look correct.
	//
	// When creating blend paths of lines, we can detect if the blend path has been reversed,
	// in relation to the original path, by the original mapping value.
	// If it's 0 it has NOT been reversed, otherwise it's been reversed.
	//
	// If the blend ratio is <=0.5, the blended path is closest to the start blend path,
	// so we look at the start blend path's original mapping.
	//
	// If blend ration > 0.5, look at the end blend path's original mapping.
	//
	// The (BlendRation <= 0.5) cut-off point is the same as the cut-off point used in the blending
	// of attributes.
	if (pBlendPathStart->IsLine() && pBlendPathEnd->IsLine())
	{
		BlendPath* pBlendPath;
		if (pParam->GetBlendRatio() <= 0.5) 
			pBlendPath = pBlendPathStart;
		else
			pBlendPath = pBlendPathEnd;

		if (pBlendPath->GetOrigMapping() != 0)
			NodeBlender::ReversePath(pDestCoords,pDestVerbs,m_ArrayLength);
	}

	// We need to do some work on the blended path
	if (!NodeBlender::ProcessBlendedPath(pDestCoords,pDestVerbs,pDestFlags,m_ArrayLength,Closed))
		return FALSE;

	Path RetnPath;
	RetnPath.Initialise(m_ArrayLength);

	BOOL Filled  = pPathStart->IsFilled  || pPathEnd->IsFilled;
	BOOL Stroked = pPathStart->IsStroked || pPathEnd->IsStroked;

	RetnPath.MergeTwoPaths(pDestCoords,pDestVerbs,pDestFlags,m_ArrayLength,Filled);

	pPath->ClearPath();
	pPath->CloneFrom(RetnPath);
	pPath->IsFilled = Filled;
	pPath->IsStroked = Stroked;
	
	return TRUE;
}