Files
GTASource/rage/scaleform/Src/GFxPlayer/GFxDrawingContext.cpp
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

261 lines
7.1 KiB
C++

/**********************************************************************
Filename : GFxDrawingContext.cpp
Content : Drawing API implementation
Created : Aug 7, 2007
Authors : Maxim Shemanarev, Artem Bolgar
Copyright : (c) 2001-2007 Scaleform Corp. All Rights Reserved.
Notes :
Licensees may use this file in accordance with the valid Scaleform
Commercial License Agreement provided with the software.
This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR ANY PURPOSE.
**********************************************************************/
#include "GFxDrawingContext.h"
#include "AMP/GFxAmpViewStats.h"
#include "GFxDisplayContext.h"
GFxDrawingContext::GFxDrawingContext() :
Shapes(*new GFxShapeWithStyles()),
PathPacker(),
FillStyle(),
LineStyle(),
NewShapeFlag(false),
FreshLineStyle(false)
{
}
void GFxDrawingContext::Clear()
{
PathPacker.Reset();
Shapes = *new GFxShapeWithStyles();
NewShapeFlag = false;
}
void GFxDrawingContext::SetNoLine()
{
PathPacker.SetLine(0);
FreshLineStyle = false;
}
void GFxDrawingContext::SetNoFill()
{
PathPacker.SetFill0(0);
PathPacker.SetFill1(0);
}
void GFxDrawingContext::SetLineStyle(Float lineWidth,
UInt rgba,
bool hinting,
GFxLineStyle::LineStyle scaling,
GFxLineStyle::LineStyle caps,
GFxLineStyle::LineStyle joins,
Float miterLimit)
{
LineStyle.SetWidth(UInt16(lineWidth));
LineStyle.SetColor(rgba);
#ifndef GFC_NO_FXPLAYER_STROKER
LineStyle.SetHinting(hinting);
LineStyle.SetScaling(scaling);
LineStyle.SetCaps(caps);
LineStyle.SetJoin(joins);
LineStyle.SetMiterSize(miterLimit);
#else
GUNUSED2(hinting, scaling);
GUNUSED3(caps, joins, miterLimit);
#endif
PathPacker.SetLine(Shapes->AddLineStyle(LineStyle));
FreshLineStyle = true;
}
bool GFxDrawingContext::SameLineStyle(Float lineWidth,
UInt rgba,
bool hinting,
GFxLineStyle::LineStyle scaling,
GFxLineStyle::LineStyle caps,
GFxLineStyle::LineStyle joins,
Float miterLimit) const
{
if (Shapes->GetNumLineStyles() == 0)
return false;
if (PathPacker.GetLine() == 0)
return false;
const GFxLineStyle& ls = Shapes->GetLastLineStyle();
if (ls.GetComplexFill() != 0)
return false;
#ifndef GFC_NO_FXPLAYER_STROKER
return ls.GetColor() == rgba &&
ls.GetWidth() == UInt(lineWidth) &&
ls.GetStrokeHinting() == hinting &&
ls.GetScaling() == scaling &&
ls.GetStartCap() == caps &&
ls.GetJoin() == joins &&
ls.GetMiterSize() == miterLimit;
#else
GUNUSED2(hinting, scaling);
GUNUSED3(caps, joins, miterLimit);
return ls.GetColor() == rgba && ls.GetWidth() == UInt(lineWidth);
#endif
}
bool GFxDrawingContext::NoLine() const
{
return Shapes->GetNumLineStyles() == 0 || PathPacker.GetLine() == 0;
}
// The function begins new fill with an "empty" style.
// It returns the pointer to just created fill style, so the caller
// can set any values. The function is used in Action Script, beginGradientFill
GFxFillStyle* GFxDrawingContext::SetNewFill()
{
FillStyle.SetFillType(GFxFill_Solid);
FillStyle.SetColor(0);
PathPacker.SetFill0(Shapes->AddFillStyle(FillStyle));
PathPacker.SetFill1(0);
return &Shapes->GetLastFillStyle();
}
GFxFillStyle* GFxDrawingContext::CreateLineComplexFill()
{
if(!FreshLineStyle)
PathPacker.SetLine(Shapes->AddLineStyle(LineStyle));
return Shapes->GetLastLineStyle().CreateComplexFill();
}
void GFxDrawingContext::SetNonZeroFill(bool fill)
{
Shapes->SetNonZeroFill(fill);
}
void GFxDrawingContext::SetFill(UInt rgba)
{
FillStyle.SetFillType(GFxFill_Solid);
FillStyle.SetColor(rgba);
PathPacker.SetFill0(Shapes->AddFillStyle(FillStyle));
PathPacker.SetFill1(0);
}
bool GFxDrawingContext::IsSolidFill(UInt rgba) const
{
return FillStyle.IsSolidFill() && FillStyle.GetColor() == rgba;
}
void GFxDrawingContext::SetBitmapFill(GFxFillType fillType,
GFxImageResource* pimageRes,
const Matrix& mtx)
{
GFxFillStyle* style = SetNewFill();
if (style)
{
style->SetImageFill(fillType, pimageRes, mtx);
}
}
void GFxDrawingContext::ResetFill()
{
PathPacker.SetFill0(0);
PathPacker.SetFill1(0);
}
void GFxDrawingContext::MoveTo(Float x, Float y)
{
PathPacker.SetMoveTo(SInt(x),
SInt(y));
}
void GFxDrawingContext::LineTo(Float x, Float y)
{
PathPacker.LineToAbs(SInt(x),
SInt(y));
FreshLineStyle = false;
}
void GFxDrawingContext::CurveTo(Float cx, Float cy, Float ax, Float ay)
{
PathPacker.CurveToAbs(SInt(cx),
SInt(cy),
SInt(ax),
SInt(ay));
FreshLineStyle = false;
}
bool GFxDrawingContext::AcquirePath(bool newShapeFlag)
{
if(!PathPacker.IsEmpty())
{
if(PathPacker.GetFill0() != 0)
{
PathPacker.ClosePath();
}
if(NewShapeFlag)
{
Shapes->StartNewShape();
}
Shapes->AddPath(&PathPacker);
Shapes->ResetCache();
Shapes->SetValidBoundsFlag(false);
PathPacker.ResetEdges();
PathPacker.SetMoveToLastVertex();
NewShapeFlag = newShapeFlag;
return true;
}
return false;
}
void GFxDrawingContext::AddPath()
{
Shapes->AddPath(&PathPacker);
}
void GFxDrawingContext::ComputeBound(GRectF *pRect) const
{
GASSERT(pRect);
const_cast<GFxDrawingContext*>(this)->AcquirePath(true);
Shapes->ComputeBound(pRect);
}
void GFxDrawingContext::Display(GFxDisplayContext &context,
const Matrix& mat,
const Cxform& cx,
BlendType blend,
bool edgeAADisabled)
{
AcquirePath(false);
if(!Shapes->IsEmpty())
{
if(!Shapes->HasValidBounds())
{
GRectF bounds;
Shapes->ComputeBound(&bounds);
Shapes->SetBound(bounds);
//Shapes->SetRectBound(bounds); // TODO: Initialize it for Flash-8 strokes features (not yet supported)
Shapes->SetValidBoundsFlag(true);
}
GFxDisplayParams params(context, mat, cx, blend);
Shapes->GetFillAndLineStyles(&params);
Shapes->Display(params, edgeAADisabled, 0);
}
}
bool GFxDrawingContext::DefPointTestLocal(const GPointF &pt, bool testShape, const GFxCharacter *pinst) const
{
const_cast<GFxDrawingContext*>(this)->AcquirePath(true);
return (Shapes->DefPointTestLocal(pt, testShape, pinst));
}