diff --git a/legacy/project/Build.xml b/legacy/project/Build.xml
index a5a5a307a..92430f854 100644
--- a/legacy/project/Build.xml
+++ b/legacy/project/Build.xml
@@ -208,6 +208,8 @@
+
+
@@ -243,6 +245,10 @@
+
+
@@ -416,6 +422,7 @@
+
diff --git a/legacy/project/include/Display.h b/legacy/project/include/Display.h
index c2ecd76ff..1759e99f8 100644
--- a/legacy/project/include/Display.h
+++ b/legacy/project/include/Display.h
@@ -192,6 +192,7 @@ public:
Graphics &GetGraphics();
virtual Matrix GetFullMatrix(bool inWithStageScaling);
Matrix &GetLocalMatrix();
+ virtual void modifyLocalMatrix(Matrix &ioMatrix) { }
ColorTransform &GetLocalColorTransform() { return colorTransform; }
ColorTransform GetFullColorTransform();
const FilterList &getFilters() { return filters; }
diff --git a/legacy/project/include/Font.h b/legacy/project/include/Font.h
index 10cc711c5..0acf1befb 100644
--- a/legacy/project/include/Font.h
+++ b/legacy/project/include/Font.h
@@ -18,7 +18,18 @@ struct TextLineMetrics
float ascent;
float descent;
float height;
+
+ void fontToLocal(double inScale)
+ {
+ ascent *= inScale;
+ descent *= inScale;
+ height = ascent + descent;
+ }
+
+ // From text format - local coords
float leading;
+
+ // The horizontal components are in local coords
float width;
float x;
};
@@ -106,9 +117,9 @@ struct CharGroup
CharGroup() : mChar0(0), mFontHeight(0), mFormat(0), mFont(0) { };
~CharGroup();
void Clear();
- bool UpdateFont(double inScale,GlyphRotation inRotation,bool inNative);
+ bool UpdateFont(double inScale,bool inNative);
void UpdateMetrics(TextLineMetrics &ioMetrics);
- int Height();
+ double Height(double inFontToLocal);
int Chars() { return mString.size(); }
void ApplyFormat(TextFormat *inFormat);
@@ -129,11 +140,11 @@ struct Line
void Clear() { memset(this,0,sizeof(*this)); }
TextLineMetrics mMetrics;
- int mY0;
- int mChar0;
- int mChars;
- int mCharGroup0;
- int mCharInGroup0;
+ float mY0;
+ int mChar0;
+ int mChars;
+ int mCharGroup0;
+ int mCharInGroup0;
};
typedef QuickVec Lines;
@@ -173,7 +184,7 @@ class Font : public Object
};
public:
- static Font *Create(TextFormat &inFormat,double inScale,GlyphRotation inRot, bool inNative,bool inInitRef=true);
+ static Font *Create(TextFormat &inFormat,double inScale, bool inNative,bool inInitRef=true);
Font *IncRef() { Object::IncRef(); return this; }
@@ -183,11 +194,9 @@ public:
bool IsNative() { return mFace && mFace->IsNative(); }
- GlyphRotation Rotation() { return mRotation; }
-
int Height();
private:
- Font(FontFace *inFace, int inPixelHeight, GlyphRotation inRotation,bool inInitRef);
+ Font(FontFace *inFace, int inPixelHeight, bool inInitRef);
~Font();
@@ -198,7 +207,6 @@ private:
int mPixelHeight;
int mCurrentSheet;
- GlyphRotation mRotation;
};
class FontCache
diff --git a/legacy/project/include/Graphics.h b/legacy/project/include/Graphics.h
index 3414e9332..b0e7571c3 100644
--- a/legacy/project/include/Graphics.h
+++ b/legacy/project/include/Graphics.h
@@ -214,7 +214,7 @@ public:
GraphicsStroke *IncRef() { Object::IncRef(); return this; }
GraphicsStroke *AsStroke() { return this; }
- int Version() const { return fill->Version(); }
+ int Version() const { return fill ? fill->Version() : 0; }
bool IsClear() { return false; }
diff --git a/legacy/project/include/TextField.h b/legacy/project/include/TextField.h
index 2077ad86a..147fa3dbd 100644
--- a/legacy/project/include/TextField.h
+++ b/legacy/project/include/TextField.h
@@ -12,8 +12,6 @@ class TiXmlNode;
namespace nme
{
-
-
class TextField : public DisplayObject
{
public:
@@ -38,10 +36,13 @@ public:
void setSelectable(bool inSelectable) { selectable = inSelectable; }
void setTextColor(int inColor);
int getTextColor() { return textColor; }
+ bool isLineVisible(int inLine) const;
bool getIsInput() { return isInput; }
void setIsInput(bool inIsInput);
AutoSizeMode getAutoSize() { return autoSize; }
void setAutoSize(int inAutoSize);
+ void modifyLocalMatrix(Matrix &ioMatrix);
+
int getCaretIndex() { return caretIndex; }
int getMaxScrollH() { Layout(); return maxScrollH; }
@@ -51,6 +52,7 @@ public:
void setScrollH(int inScrollH);
int getScrollV() { return scrollV; }
void setScrollV(int inScrollV);
+ void setScrollVClearSel(int inScrollV,bool inClearSel);
int getNumLines() { Layout(); return mLines.size(); }
int getSelectionBeginIndex();
int getSelectionEndIndex();
@@ -80,6 +82,8 @@ public:
int getLineOffset(int inLine);
WString getLineText(int inLine);
+ void toScreenGrid(UserPoint &ioPoint,const Matrix &inMatrix);
+ void highlightRect(double x0, double y1, double w, double h);
TextLineMetrics *getLineMetrics(int inLine);
double getWidth();
@@ -92,7 +96,7 @@ public:
WString getText();
void setText(const WString &inString);
- int getLength();
+ int getLength() const;
double getTextHeight();
double getTextWidth();
@@ -130,19 +134,17 @@ public:
void Render( const RenderTarget &inTarget, const RenderState &inState );
- // Display-object like properties
- // Glyphs are laid out in a local pixel coordinate space, which is related to the
- // render-target window co-ordinates by the folling members
- double mLayoutScaleH;
- double mLayoutScaleV;
- GlyphRotation mLayoutRotation;
- // Unscaled size, as specified by application
- double boundsWidth;
- double boundsHeight;
- // Local pixel space
- int textWidth;
- int textHeight;
- Rect mActiveRect;
+ bool screenGrid;
+ double fontScale;
+ double fontToLocal;
+
+ // Local coordinates
+ double explicitWidth;
+ double fieldWidth;
+ double fieldHeight;
+ double textWidth;
+ double textHeight;
+ DRect mActiveRect;
void GetExtent(const Transform &inTrans, Extent2DF &outExt,bool inForBitmap,bool inIncludeStroke);
Cursor GetCursor();
@@ -153,6 +155,7 @@ public:
void OnKey(Event &inEvent);
void OnScrollWheel(int inDirection);
void DeleteSelection();
+ void ClearSelection();
void DeleteChars(int inFirst,int inEnd);
void InsertString(WString &ioString);
void ShowCaret(bool inFromDrag=false);
@@ -185,30 +188,32 @@ private:
void SplitGroup(int inGroup,int inPos);
void BuildBackground();
- UserPoint TargetToRect(const Matrix &inMat,const UserPoint &inPoint);
- UserPoint RectToTarget(const Matrix &inMat,const UserPoint &inPoint);
- int PointToChar(int inX,int inY);
+ int PointToChar(UserPoint inPoint) const;
int LineFromChar(int inChar);
int GroupFromChar(int inChar);
- int EndOfCharX(int inChar,int inLine);
- int EndOfLineX(int inLine);
- ImagePoint GetScrollPos();
- ImagePoint GetCursorPos();
+ double EndOfCharX(int inChar,int inLine) const;
+ double EndOfLineX(int inLine) const;
+ UserPoint GetScrollPos() const;
+ UserPoint GetCursorPos() const;
void OnChange();
bool mLinesDirty;
bool mGfxDirty;
bool mFontsDirty;
+ bool mTilesDirty;
+ bool mCaretDirty;
bool mHasCaret;
+ double mBlink0;
CharGroups mCharGroups;
Lines mLines;
- QuickVec mCharPos;
+ QuickVec mCharPos;
Graphics *mCaretGfx;
Graphics *mHighlightGfx;
+ Graphics *mTiles;
int mLastCaretHeight;
int mLastUpDownX;
diff --git a/legacy/project/include/Tilesheet.h b/legacy/project/include/Tilesheet.h
index f4bfb5365..72618121a 100644
--- a/legacy/project/include/Tilesheet.h
+++ b/legacy/project/include/Tilesheet.h
@@ -23,7 +23,7 @@ public:
Tilesheet *IncRef() { Object::IncRef(); return this; }
- int AllocRect(int inW,int inH,float inOx = 0, float inOy = 0);
+ int AllocRect(int inW,int inH,float inOx = 0, float inOy = 0,bool inAlphaBorder=false);
int addTileRect(const Rect &inRect,float inOx=0, float inOy=0);
const Tile &GetTile(int inID) { return mTiles[inID]; }
Surface &GetSurface() { return *mSheet; }
diff --git a/legacy/project/include/nme/NmeCffi.h b/legacy/project/include/nme/NmeCffi.h
index d4c26ce2f..8def02e09 100644
--- a/legacy/project/include/nme/NmeCffi.h
+++ b/legacy/project/include/nme/NmeCffi.h
@@ -11,24 +11,26 @@ namespace nme
extern vkind gObjectKind;
+
+namespace
+{
+ inline void release_object(value inValue)
+ {
+ if (val_is_kind(inValue,gObjectKind))
+ {
+ Object *obj = (Object *)val_to_kind(inValue,gObjectKind);
+ if (obj)
+ obj->DecRef();
+ }
+ }
+}
+
+
inline value ObjectToAbstract(Object *inObject)
{
- struct releaser
- {
- static void release_object(value inValue)
- {
- if (val_is_kind(inValue,gObjectKind))
- {
- Object *obj = (Object *)val_to_kind(inValue,gObjectKind);
- if (obj)
- obj->DecRef();
- }
- }
- };
-
inObject->IncRef();
value result = alloc_abstract(gObjectKind,inObject);
- val_gc(result,releaser::release_object);
+ val_gc(result,release_object);
return result;
}
diff --git a/legacy/project/include/nme/Pixel.h b/legacy/project/include/nme/Pixel.h
index e0df01815..27d38a528 100644
--- a/legacy/project/include/nme/Pixel.h
+++ b/legacy/project/include/nme/Pixel.h
@@ -39,6 +39,11 @@ struct ARGB
a = alpha<0 ? 0 : alpha >255 ? 255 : alpha;
}
+ inline float getRedFloat() { return r/255.0; }
+ inline float getGreenFloat() { return g/255.0; }
+ inline float getBlueFloat() { return b/255.0; }
+ inline float getAlphaFloat() { return a/255.0; }
+
inline int ToInt() const { return ival; }
inline void Set(int inVal) { ival = inVal; }
inline void SetRGB(int inVal) { ival = inVal | 0xff000000; }
diff --git a/legacy/project/src/ExternalInterface.cpp b/legacy/project/src/ExternalInterface.cpp
index 7fddc551c..d9d754dd0 100644
--- a/legacy/project/src/ExternalInterface.cpp
+++ b/legacy/project/src/ExternalInterface.cpp
@@ -397,6 +397,7 @@ namespace nme {
DEFINE_LIME_PRIM_1(font_set_factory);
DEFINE_LIME_PRIM_2(font_register_font);
DEFINE_LIME_PRIM_0(gl_get_error);
+ DEFINE_LIME_PRIM_1(gl_get_extension);
DEFINE_LIME_PRIM_0(gl_finish);
DEFINE_LIME_PRIM_0(gl_flush);
DEFINE_LIME_PRIM_0(gl_version);
diff --git a/legacy/project/src/common/CURL.cpp b/legacy/project/src/common/CURL.cpp
index fd18315f8..6d2eab489 100644
--- a/legacy/project/src/common/CURL.cpp
+++ b/legacy/project/src/common/CURL.cpp
@@ -405,7 +405,7 @@ extern get_file_callback_func get_file_callback;
}
#if (defined(HX_MACOS) || defined(ANDROID) ) && defined(NME_CURL_SSL)
-//#define TRY_GET_FILE
+#define TRY_GET_FILE
#endif
#ifdef TRY_GET_FILE
diff --git a/legacy/project/src/common/Display.cpp b/legacy/project/src/common/Display.cpp
index 9046e44fd..a3b55a4f3 100644
--- a/legacy/project/src/common/Display.cpp
+++ b/legacy/project/src/common/Display.cpp
@@ -2,7 +2,6 @@
#include
#include
-#include "TextField.h"
#ifndef M_PI
#define M_PI 3.1415926535897932385
@@ -12,11 +11,6 @@
#include
#endif
-#if defined(NME_S3D) && defined(ANDROID)
-#include
-#include
-#endif
-
namespace nme
{
@@ -300,7 +294,8 @@ void DisplayObject::DirtyCache(bool inParentOnly)
Matrix DisplayObject::GetFullMatrix(bool inStageScaling)
{
if (mParent)
- return mParent->GetFullMatrix(inStageScaling).Mult(GetLocalMatrix().Translated(-scrollRect.x,-scrollRect.y));
+ return mParent->GetFullMatrix(inStageScaling).Mult(GetLocalMatrix().
+ Translated(-scrollRect.x,-scrollRect.y));
return GetLocalMatrix().Translated(-scrollRect.x,-scrollRect.y);
}
@@ -350,6 +345,7 @@ Matrix &DisplayObject::GetLocalMatrix()
#ifdef NME_S3D
mLocalMatrix.mtz = z;
#endif
+ modifyLocalMatrix(mLocalMatrix);
}
return mLocalMatrix;
}
@@ -1528,764 +1524,7 @@ void DisplayObjectContainer::ClearCacheDirty()
}
-// --- BitmapCache ---------------------------------------------------------
-static int sBitmapVersion = 1;
-
-BitmapCache::BitmapCache(Surface *inSurface,const Transform &inTrans,
- const Rect &inRect,bool inMaskOnly, BitmapCache *inMask)
-{
- mBitmap = inSurface->IncRef();
- mMatrix = *inTrans.mMatrix;
- mScale9 = *inTrans.mScale9;
- mRect = inRect;
- mVersion = sBitmapVersion++;
- if (!mVersion)
- mVersion = sBitmapVersion++;
- mMaskVersion = inMask ? inMask->mVersion : 0;
- mMaskOffset = inMask ? ImagePoint(inMask->mTX,inMask->mTY) : ImagePoint(0,0);
- mTX = mTY = 0;
-}
-
-BitmapCache::~BitmapCache()
-{
- mBitmap->DecRef();
-}
-
-
-bool BitmapCache::StillGood(const Transform &inTransform, const Rect &inVisiblePixels, BitmapCache *inMask)
-{
- if (!mMatrix.IsIntTranslation(*inTransform.mMatrix,mTX,mTY) || mScale9!=*inTransform.mScale9)
- return false;
-
- if (inMask)
- {
- if (inMask->mVersion!=mMaskVersion)
- return false;
- if (mMaskOffset != ImagePoint(inMask->mTX, inMask->mTY) )
- return false;
- }
- else if (mMaskVersion)
- return false;
-
- // Translate our cached pixels to this new position ...
- Rect translated = mRect.Translated(mTX,mTY);
- if (translated.Contains(inVisiblePixels))
- return true;
-
- return false;
-}
-
-
-void BitmapCache::Render(const RenderTarget &inTarget,const Rect &inClipRect, const BitmapCache *inMask,BlendMode inBlend)
-{
- if (mBitmap)
- {
- int tint = 0xffffffff;
- if (inTarget.mPixelFormat!=pfAlpha && mBitmap->Format()==pfAlpha)
- tint = 0xff000000;
-
- Rect src( mRect.x+mTX, mRect.y+mTY, mRect.w, mRect.h);
- int ox = src.x;
- int oy = src.y;
- src = src.Intersect(inClipRect);
- if (!src.HasPixels())
- return;
- ox -= src.x;
- oy -= src.y;
- src.Translate(-mRect.x - mTX,-mRect.y-mTY);
-
-
- if (inTarget.IsHardware())
- {
- //__android_log_print(ANDROID_LOG_INFO,"BitmapCache", "Render %dx%d + (%d,%d) -> %dx%d + (%d,%d)",
- //mRect.w,mRect.h, mRect.x + mTX , mRect.y+mTY,
- //inTarget.mRect.w, inTarget.mRect.h, inTarget.mRect.x, inTarget.mRect.y );
- inTarget.mHardware->SetViewport(inTarget.mRect);
- inTarget.mHardware->BeginBitmapRender(mBitmap,tint);
- inTarget.mHardware->RenderBitmap(src, mRect.x+mTX-ox, mRect.y+mTY-oy);
- inTarget.mHardware->EndBitmapRender();
- }
- else
- {
- // TX,TX is set in StillGood function
- mBitmap->BlitTo(inTarget, src, mRect.x+mTX-ox, mRect.y+mTY-oy,inBlend,inMask,tint);
- }
- }
-}
-
-void BitmapCache::PushTargetOffset(const ImagePoint &inOffset, ImagePoint &outBuffer)
-{
- outBuffer = ImagePoint(mTX,mTY);
- mTX -= inOffset.x;
- mTY -= inOffset.y;
-}
-
-void BitmapCache::PopTargetOffset(ImagePoint &inBuffer)
-{
- mTX = inBuffer.x;
- mTY = inBuffer.y;
-}
-
-
-bool BitmapCache::HitTest(double inX, double inY)
-{
- double x0 = mRect.x+mTX;
- double y0 = mRect.y+mTY;
- //printf("BMP hit %f,%f %f,%f ... %d,%d\n", inX, inY, x0,y0, mRect.w, mRect.h );
- return x0<=inX && y0<=inY && (inX<=x0+mRect.w) && (inY<=y0+mRect.h);
-}
-
-
-
-// --- Stage ---------------------------------------------------------------
-
-
-// Helper class....
-class AutoStageRender
-{
- Surface *mSurface;
- Stage *mToFlip;
- RenderTarget mTarget;
-public:
- AutoStageRender(Stage *inStage,int inRGB)
- {
- mSurface = inStage->GetPrimarySurface();
- mToFlip = inStage;
- mTarget = mSurface->BeginRender( Rect(mSurface->Width(),mSurface->Height()),false );
-
- mSurface->Clear( (inRGB | 0xff000000) & inStage->getBackgroundMask() );
- }
- int Width() const { return mSurface->Width(); }
- int Height() const { return mSurface->Height(); }
- ~AutoStageRender()
- {
- mSurface->EndRender();
- mToFlip->Flip();
- }
- const RenderTarget &Target() { return mTarget; }
-};
-
-Stage *Stage::gCurrentStage = 0;
-
-Stage::Stage(bool inInitRef) : DisplayObjectContainer(inInitRef)
-{
- gCurrentStage = this;
- mHandler = 0;
- mHandlerData = 0;
- opaqueBackground = 0xffffffff;
- mFocusObject = 0;
- mMouseDownObject = 0;
- mSimpleButton = 0;
- focusRect = true;
- mLastMousePos = UserPoint(0,0);
- scaleMode = ssmShowAll;
- mNominalWidth = 100;
- mNominalHeight = 100;
- mNextWake = 0.0;
- displayState = sdsNormal;
- align = saTopLeft;
- #ifdef NME_S3D
- autos3d = true;
- #endif
-
- #if defined(IPHONE) || defined(ANDROID) || defined(WEBOS) || defined(TIZEN)
- quality = sqLow;
- #else
- quality = sqBest;
- #endif
-}
-
-Stage::~Stage()
-{
- if (gCurrentStage==this)
- gCurrentStage = 0;
- if (mFocusObject)
- mFocusObject->DecRef();
- if (mMouseDownObject)
- mMouseDownObject->DecRef();
-}
-
-void Stage::SetNextWakeDelay(double inNextWake)
-{
- mNextWake = inNextWake + GetTimeStamp();
-}
-
-void Stage::SetFocusObject(DisplayObject *inObj,FocusSource inSource,int inKey)
-{
- if (inObj==mFocusObject)
- return;
-
- if (mHandler)
- {
- Event focus(etFocus);
- focus.id = inObj ? inObj->id : 0;
- focus.value = inSource;
- focus.code = inKey;
-
- mHandler(focus,mHandlerData);
-
- if (inSource!=fsProgram && focus.result==erCancel)
- return;
- }
-
-
- if (!inObj || inObj->getStage()!=this)
- {
- if (mFocusObject)
- {
- mFocusObject->Unfocus();
- mFocusObject->DecRef();
- }
- mFocusObject = 0;
- }
- else
- {
- inObj->IncRef();
- if (mFocusObject)
- {
- mFocusObject->Unfocus();
- mFocusObject->DecRef();
- }
- mFocusObject = inObj;
- inObj->Focus();
- }
-
-}
-
-void Stage::SetNominalSize(int inWidth, int inHeight)
-{
- mNominalWidth = inWidth;
- mNominalHeight = inHeight;
- CalcStageScaling( getStageWidth(), getStageHeight() );
-}
-
-
-void Stage::SetEventHandler(EventHandler inHander,void *inUserData)
-{
- mHandler = inHander;
- mHandlerData = inUserData;
-}
-
-void Stage::HandleEvent(Event &inEvent)
-{
- gCurrentStage = this;
- DisplayObject *hit_obj = 0;
-
- bool primary = inEvent.flags & efPrimaryTouch;
-
- if ( (inEvent.type==etMouseMove || inEvent.type==etMouseDown ||
- inEvent.type==etTouchBegin || inEvent.type==etTouchMove )
- && primary )
- mLastMousePos = UserPoint(inEvent.x, inEvent.y);
-
- if (mMouseDownObject && primary)
- {
- switch(inEvent.type)
- {
- case etTouchMove:
- case etMouseMove:
- if (inEvent.flags & efLeftDown)
- {
- mMouseDownObject->Drag(inEvent);
- break;
- }
- // fallthrough
- case etMouseClick:
- case etMouseDown:
- case etMouseUp:
- case etTouchBegin:
- case etTouchTap:
- case etTouchEnd:
- mMouseDownObject->EndDrag(inEvent);
- mMouseDownObject->DecRef();
- mMouseDownObject = 0;
- break;
- default: break;
- }
- }
-
- if (inEvent.type==etKeyDown || inEvent.type==etKeyUp)
- {
- inEvent.id = mFocusObject ? mFocusObject->id : id;
- if (mHandler)
- mHandler(inEvent,mHandlerData);
- if (inEvent.result==0 && mFocusObject)
- mFocusObject->OnKey(inEvent);
- #ifdef ANDROID
- // Non-cancelled back key ...
- if (inEvent.result==0 && inEvent.value==27 && inEvent.type == etKeyUp)
- {
- StopAnimation();
- }
- #endif
- return;
- }
-
- if (inEvent.type==etResize)
- {
- CalcStageScaling( inEvent.x, inEvent.y);
- }
-
- if (inEvent.type==etMouseMove || inEvent.type==etMouseDown ||
- inEvent.type==etMouseUp || inEvent.type==etMouseClick ||
- inEvent.type==etTouchBegin || inEvent.type==etTouchEnd ||
- inEvent.type==etTouchMove || inEvent.type==etTouchTap
- )
- {
- UserPoint pixels(inEvent.x,inEvent.y);
- hit_obj = HitTest(pixels);
- //if (inEvent.type!=etTouchMove)
- //ELOG(" type=%d %d,%d obj=%p (%S)", inEvent.type, inEvent.x, inEvent.y, hit_obj, hit_obj?hit_obj->name.c_str():L"(none)");
-
- SimpleButton *but = hit_obj ? dynamic_cast(hit_obj) : 0;
- inEvent.id = hit_obj ? hit_obj->id : id;
- Cursor cur = hit_obj ? hit_obj->GetCursor() : curPointer;
-
- if (mSimpleButton && (inEvent.flags & efLeftDown) )
- {
- // Don't change simple button if dragging ...
- }
- else if (but!=mSimpleButton)
- {
- if (but)
- but->IncRef();
- if (mSimpleButton)
- {
- SimpleButton *s = mSimpleButton;
- mSimpleButton = 0;
- s->setMouseState(SimpleButton::stateUp);
- s->DecRef();
- }
- mSimpleButton = but;
- }
-
- if (mSimpleButton)
- {
- bool over = but==mSimpleButton;
- bool down = (inEvent.flags & efLeftDown);
- mSimpleButton->setMouseState( over ? ( down ?
- SimpleButton::stateDown : SimpleButton::stateOver) : SimpleButton::stateUp );
- if (!down && !over)
- {
- SimpleButton *s = mSimpleButton;
- mSimpleButton = 0;
- s->DecRef();
- }
- else if (mSimpleButton->getUseHandCursor())
- cur = curHand;
- }
-
- SetCursor( (gMouseShowCursor || cur>=curTextSelect0) ? cur : curNone );
-
- UserPoint stage = mStageScale.ApplyInverse(pixels);
- inEvent.x = stage.x;
- inEvent.y = stage.y;
- }
-
-
- if (hit_obj)
- hit_obj->IncRef();
-
- if (mHandler)
- mHandler(inEvent,mHandlerData);
-
- if (hit_obj)
- {
- if ( (inEvent.type==etMouseDown ||
- (inEvent.type==etTouchBegin && (inEvent.flags & efPrimaryTouch) ))
- && inEvent.result!=erCancel )
- {
- if (hit_obj->WantsFocus())
- SetFocusObject(hit_obj,fsMouse);
- #if defined(IPHONE) || defined(ANDROID) || defined(WEBOS) || defined(TIZEN)
- else
- {
- EnablePopupKeyboard(false);
- SetFocusObject(0,fsMouse);
- }
- #endif
- }
-
- if (inEvent.type==etMouseDown || (inEvent.type==etTouchBegin && primary) )
- {
- if (hit_obj->CaptureDown(inEvent))
- {
- hit_obj->IncRef();
- mMouseDownObject = hit_obj;
- }
- }
- if (inEvent.type==etMouseUp && (inEvent.value==3 || inEvent.value==4) )
- {
- TextField *text = dynamic_cast(hit_obj);
- if (text && text->mouseWheelEnabled)
- text->OnScrollWheel(inEvent.value==3 ? -1 : 1);
- }
- }
- #if defined(IPHONE) || defined(ANDROID) || defined(WEBOS) || defined(TIZEN)
- else if (inEvent.type==etMouseClick || inEvent.type==etMouseDown ||
- (inEvent.type==etTouchBegin && (inEvent.flags & efPrimaryTouch) ))
- {
- EnablePopupKeyboard(false);
- SetFocusObject(0);
- }
- #endif
-
-
- if (hit_obj)
- hit_obj->DecRef();
-}
-
-void Stage::setOpaqueBackground(uint32 inBG)
-{
- opaqueBackground = inBG | 0xff000000;
- DirtyCache();
-}
-
-
-void Stage::RemovingFromStage(DisplayObject *inObject)
-{
- DisplayObject *b = mSimpleButton;
- while(b)
- {
- if (b==inObject)
- {
- mSimpleButton->DecRef();
- mSimpleButton = 0;
- break;
- }
- b = b->getParent();
- }
-
-
- DisplayObject *f = mFocusObject;
- while(f)
- {
- if (f==inObject)
- {
- mFocusObject->DecRef();
- mFocusObject = 0;
- break;
- }
- f = f->getParent();
- }
-
- DisplayObject *m = mMouseDownObject;
- while(m)
- {
- if (m==inObject)
- {
- mMouseDownObject->DecRef();
- mMouseDownObject = 0;
- break;
- }
- m = m->getParent();
- }
-
-}
-
-
-void Stage::CalcStageScaling(double inNewWidth,double inNewHeight)
-{
- double StageScaleX=1;
- double StageScaleY=1;
- double StageOX=0;
- double StageOY=0;
-
- if (inNewWidth<=0 || inNewHeight<=0)
- return;
-
- if (scaleMode!=ssmNoScale)
- {
- StageScaleX = inNewWidth/(double)mNominalWidth;
- StageScaleY = inNewHeight/(double)mNominalHeight;
-
- if (scaleMode==ssmNoBorder)
- {
- if (StageScaleX>StageScaleY)
- StageScaleY = StageScaleX;
- else
- StageScaleX = StageScaleY;
- }
- else if (scaleMode==ssmShowAll)
- {
- if (StageScaleXFinishEditOnEnter();
- return false;
-}
-
-int Stage::GetAA()
-{
- switch(quality)
- {
- case sqLow: return 1;
- case sqMedium: return 2;
- case sqHigh:
- case sqBest:
- return 4;
- }
- return 1;
-}
-
-
-#ifdef HX_LIME // {
-
-void Stage::RenderStage()
-{
- ColorTransform::TidyCache();
- AutoStageRender render(this,opaqueBackground);
-
- #if !defined(NME_S3D) || !defined(ANDROID)
-
- if (render.Target().IsHardware())
- render.Target().mHardware->SetQuality(quality);
-
- RenderState state(0, GetAA() );
-
- state.mTransform.mMatrix = &mStageScale;
-
- state.mClipRect = Rect( render.Width(), render.Height() );
-
- state.mPhase = rpBitmap;
- state.mRoundSizeToPOW2 = render.Target().IsHardware();
- Render(render.Target(),state);
-
- state.mPhase = rpRender;
- Render(render.Target(),state);
-
- #else
-
- S3DEye start = EYE_MIDDLE;
- S3DEye end = EYE_MIDDLE;
- if(autos3d && S3D::GetEnabled()) {
-
- start = EYE_LEFT;
- end = EYE_RIGHT;
-
- }
-
- for(int eye = start; eye <= end; eye++) {
-
- if (render.Target().IsHardware())
- {
- render.Target().mHardware->SetS3DEye(eye);
- render.Target().mHardware->SetQuality(quality);
- }
-
- RenderState state(0, GetAA() );
-
- state.mTransform.mMatrix = &mStageScale;
-
- state.mClipRect = Rect( render.Width(), render.Height() );
-
- state.mPhase = rpBitmap;
- state.mRoundSizeToPOW2 = render.Target().IsHardware();
- Render(render.Target(),state);
-
- state.mPhase = rpRender;
- Render(render.Target(),state);
-
- }
-
- if(autos3d && S3D::GetEnabled()) {
- render.Target().mHardware->EndS3DRender();
- }
-
- #endif
-
- // Clear alpha masks
-}
-void Stage::BeginRenderStage(bool) { }
-void Stage::EndRenderStage() { }
-
-#else // } nme(not lime) split render stage into 3 phases .. {
-
-void Stage::BeginRenderStage(bool inClear)
-{
- Surface *surface = GetPrimarySurface();
- currentTarget = surface->BeginRender( Rect(surface->Width(),surface->Height()),false );
- if (inClear)
- surface->Clear( (opaqueBackground | 0xff000000) & getBackgroundMask() );
-}
-
-void Stage::RenderStage()
-{
- ColorTransform::TidyCache();
-
- if (currentTarget.IsHardware())
- currentTarget.mHardware->SetQuality(quality);
-
- RenderState state(0, GetAA() );
-
- state.mTransform.mMatrix = &mStageScale;
-
- state.mClipRect = Rect( currentTarget.Width(), currentTarget.Height() );
-
- state.mPhase = rpBitmap;
- state.mRoundSizeToPOW2 = currentTarget.IsHardware();
- Render(currentTarget,state);
-
- state.mPhase = rpRender;
- Render(currentTarget,state);
-}
-
-void Stage::EndRenderStage()
-{
- currentTarget = RenderTarget();
- GetPrimarySurface()->EndRender();
- ClearCacheDirty();
- Flip();
-}
-
-#endif // }
-
-bool Stage::BuildCache()
-{
- Surface *surface = GetPrimarySurface();
- RenderState state(surface, GetAA() );
- state.mTransform.mMatrix = &mStageScale;
- bool wasDirty = false;
- state.mWasDirtyPtr = &wasDirty;
-
- state.mPhase = rpBitmap;
-
- RenderTarget target(state.mClipRect, surface->GetHardwareRenderer());
- state.mRoundSizeToPOW2 = surface->GetHardwareRenderer();
- Render(target,state);
-
- return wasDirty;
-}
-
-double Stage::getStageWidth()
-{
- Surface *s = GetPrimarySurface();
- if (!s) return 0;
- return s->Width();
-}
-
-double Stage::getStageHeight()
-{
- Surface *s = GetPrimarySurface();
- if (!s) return 0;
- return s->Height();
-}
-
-
-void Stage::setScaleMode(int inMode)
-{
- scaleMode = (StageScaleMode)inMode;
- CalcStageScaling( getStageWidth(), getStageHeight() );
-}
-
-void Stage::setAlign(int inAlign)
-{
- align = (StageAlign)inAlign;
- CalcStageScaling( getStageWidth(), getStageHeight() );
-}
-
-void Stage::setQuality(int inQuality)
-{
- quality = (StageQuality)inQuality;
- DirtyCache();
-}
-
-void Stage::setDisplayState(int inDisplayState)
-{
- displayState = (StageDisplayState)inDisplayState;
- SetFullscreen(inDisplayState>0);
-}
-
-
-Matrix Stage::GetFullMatrix(bool inStageScaling)
-{
- if (!inStageScaling)
- return DisplayObject::GetFullMatrix(false);
-
- return mStageScale.Mult(GetLocalMatrix());
-}
-
-
-
-DisplayObject *Stage::HitTest(UserPoint inStage,DisplayObject *inRoot,bool inRecurse)
-{
- Surface *surface = GetPrimarySurface();
-
- RenderTarget target = surface->BeginRender( Rect(surface->Width(),surface->Height()),true );
-
- RenderState state(0, GetAA() );
- state.mClipRect = Rect( inStage.x, inStage.y, 1, 1 );
- Matrix m = mStageScale;
- if (inRoot)
- m = inRoot->GetFullMatrix(true);
- state.mTransform.mMatrix = &m;
-
-
- state.mRoundSizeToPOW2 = target.IsHardware();
- state.mPhase = rpHitTest;
- state.mRecurse = inRecurse;
-
- (inRoot ? inRoot : this) -> Render(target,state);
-
- surface->EndRender();
-
- // ELOG("Stage hit %f,%f -> %p\n", inStage.x, inStage.y, state.mHitResult );
-
- return state.mHitResult;
-}
} // end namespace nme
diff --git a/legacy/project/src/common/ExternalInterface.cpp b/legacy/project/src/common/ExternalInterface.cpp
index 90438cff0..6acc72ab2 100644
--- a/legacy/project/src/common/ExternalInterface.cpp
+++ b/legacy/project/src/common/ExternalInterface.cpp
@@ -576,7 +576,8 @@ void ToValue(value &outVal,const ColorTransform &inTrans)
void FromValue(value obj, URLRequest &request)
{
request.url = val_string( val_field(obj, _id_url) );
- request.userAgent = val_string( val_field(obj, _id_userAgent) );
+ value userAgent = val_field(obj, _id_userAgent);
+ request.userAgent = val_is_string(userAgent) ? val_string( userAgent ) : "";
request.authType = val_field_numeric(obj, _id_authType );
request.credentials = val_string( val_field(obj, _id_credentials) );
request.cookies = val_string( val_field(obj, _id_cookieString) );
diff --git a/legacy/project/src/common/Font.cpp b/legacy/project/src/common/Font.cpp
index 34fc9c8b0..1a04cd74b 100644
--- a/legacy/project/src/common/Font.cpp
+++ b/legacy/project/src/common/Font.cpp
@@ -140,10 +140,9 @@ FontFace *FontFace::CreateCFFIFont(const TextFormat &inFormat,double inScale)
// --- Font ----------------------------------------------------------------
-Font::Font(FontFace *inFace, int inPixelHeight, GlyphRotation inRotation,bool inInitRef) :
+Font::Font(FontFace *inFace, int inPixelHeight, bool inInitRef) :
Object(inInitRef), mFace(inFace), mPixelHeight(inPixelHeight)
{
- mRotation = inRotation;
mCurrentSheet = -1;
}
@@ -185,40 +184,19 @@ Tile Font::GetGlyph(int inCharacter,int &outAdvance)
int orig_w = gw;
int orig_h = gh;
- switch(mRotation)
- {
- case gr0: break;
- case gr270:
- std::swap(gw,gh);
- std::swap(ox,oy);
- oy = -gh-oy;
- break;
- case gr180:
- ox = -gw-ox;
- oy = -gh-oy;
- break;
- case gr90:
- std::swap(gw,gh);
- std::swap(ox,oy);
- ox = -gw-ox;
- break;
- }
-
while(1)
{
// Allocate new sheet?
if (mCurrentSheet<0)
{
- int rows = mPixelHeight > 128 ? 1 : mPixelHeight > 64 ? 2 : mPixelHeight>32 ? 4 : 5;
+ int rows = mPixelHeight > 127 ? 1 : mPixelHeight > 63 ? 2 : mPixelHeight>31 ? 4 : 5;
int h = 4;
- while(hWantRGB() ? pfARGB : pfAlpha;
Tilesheet *sheet = new Tilesheet(w,h,pf,true);
sheet->GetSurface().Clear(0);
@@ -226,7 +204,7 @@ Tile Font::GetGlyph(int inCharacter,int &outAdvance)
mSheets.push_back(sheet);
}
- int tid = mSheets[mCurrentSheet]->AllocRect(gw,gh,ox,oy);
+ int tid = mSheets[mCurrentSheet]->AllocRect(gw,gh,ox,oy,true);
if (tid>=0)
{
glyph.sheet = mCurrentSheet;
@@ -251,50 +229,8 @@ Tile Font::GetGlyph(int inCharacter,int &outAdvance)
*dest++ = 0xff;
}
}
- else if (mRotation==gr0)
- mFace->RenderGlyph(inCharacter,target);
else
- {
- SimpleSurface *buf = new SimpleSurface(orig_w,orig_h,pfAlpha,true);
- buf->IncRef();
- {
- AutoSurfaceRender renderer(buf);
- mFace->RenderGlyph(inCharacter,renderer.Target());
- }
-
- const uint8 *src;
- for(int y=0; yRow(0) + buf->Width() -1 - y;
- for(int x=0; xGetStride();
- }
- break;
- case gr180:
- src = buf->Row(buf->Height()-1-y) + buf->Width() -1;
- for(int x=0; xRow(buf->Height()-1) + y;
- for(int x=0; xGetStride();
- }
- break;
- }
- }
- buf->DecRef();
- }
+ mFace->RenderGlyph(inCharacter,target);
tile.mSurface->EndRender();
outAdvance = glyph.advance;
@@ -327,8 +263,8 @@ void CharGroup::UpdateMetrics(TextLineMetrics &ioMetrics)
mFont->UpdateMetrics(ioMetrics);
}
-int CharGroup::Height()
-{ return mFont ? mFont->Height() : 12; }
+double CharGroup::Height(double inFontToLocal)
+ { return inFontToLocal * (mFont ? mFont->Height() : 12); }
// --- Create font from TextFormat ----------------------------------------------------
@@ -339,7 +275,7 @@ int CharGroup::Height()
struct FontInfo
{
- FontInfo(const TextFormat &inFormat,double inScale,GlyphRotation inRotation,bool inNative)
+ FontInfo(const TextFormat &inFormat,double inScale,bool inNative)
{
name = inFormat.font;
height = (int )(inFormat.size*inScale + 0.5);
@@ -349,7 +285,6 @@ struct FontInfo
flags |= ffBold;
if (inFormat.italic)
flags |= ffItalic;
- rotation = inRotation;
}
bool operator<(const FontInfo &inRHS) const
@@ -360,15 +295,12 @@ struct FontInfo
if (height > inRHS.height) return false;
if (!native && inRHS.native) return true;
if (native && !inRHS.native) return false;
- if (rotation < inRHS.rotation) return true;
- if (rotation > inRHS.rotation) return false;
return flags < inRHS.flags;
}
WString name;
bool native;
int height;
unsigned int flags;
- GlyphRotation rotation;
};
@@ -377,9 +309,9 @@ FontMap sgFontMap;
typedef std::map FontBytesMap;
FontBytesMap sgRegisteredFonts;
-Font *Font::Create(TextFormat &inFormat,double inScale,GlyphRotation inRotation,bool inNative,bool inInitRef)
+Font *Font::Create(TextFormat &inFormat,double inScale,bool inNative,bool inInitRef)
{
- FontInfo info(inFormat,inScale,inRotation,inNative);
+ FontInfo info(inFormat,inScale,inNative);
Font *font = 0;
FontMap::iterator fit = sgFontMap.find(info);
@@ -419,7 +351,7 @@ Font *Font::Create(TextFormat &inFormat,double inScale,GlyphRotation inRotation,
if (!face)
return 0;
- font = new Font(face,info.height,inRotation,inInitRef);
+ font = new Font(face,info.height,inInitRef);
// Store for Ron ...
font->IncRef();
sgFontMap[info] = font;
diff --git a/legacy/project/src/common/FreeType.cpp b/legacy/project/src/common/FreeType.cpp
index cf2afb244..e9f97e6c0 100644
--- a/legacy/project/src/common/FreeType.cpp
+++ b/legacy/project/src/common/FreeType.cpp
@@ -345,12 +345,14 @@ bool GetFontFile(const std::string& inName,std::string &outFile)
bool GetFontFile(const std::string& inName,std::string &outFile)
{
+ const char *alternate = 0;
if (!strcasecmp(inName.c_str(),"_serif") ||
!strcasecmp(inName.c_str(),"times.ttf") || !strcasecmp(inName.c_str(),"times"))
{
#if defined (ANDROID)
outFile = "/system/fonts/DroidSerif-Regular.ttf";
+ alternate = "/system/fonts/NotoSerif-Regular.ttf";
#elif defined (WEBOS)
outFile = "/usr/share/fonts/times.ttf";
#elif defined (BLACKBERRY)
@@ -405,6 +407,13 @@ bool GetFontFile(const std::string& inName,std::string &outFile)
}
#ifdef ANDROID
+ if (alternate)
+ {
+ struct stat s;
+ if (stat(outFile.c_str(),&s)!=0 && stat(alternate,&s)==0)
+ outFile = alternate;
+ }
+
//__android_log_print(ANDROID_LOG_INFO, "GetFontFile", "mapped '%s' to '%s'.", inName.c_str(), outFile.c_str());
#endif
return true;
diff --git a/legacy/project/src/common/Hardware.cpp b/legacy/project/src/common/Hardware.cpp
index bab599efc..67e6221fc 100644
--- a/legacy/project/src/common/Hardware.cpp
+++ b/legacy/project/src/common/Hardware.cpp
@@ -6,7 +6,6 @@
#define M_PI 3.14159265358979323846
#endif
-
namespace nme
{
@@ -611,11 +610,59 @@ public:
PushElement();
}
+ void PushOutline(const Vertices &inV)
+ {
+ ReserveArrays(inV.size()+1);
+
+ //printf("PushVertices %d\n", inV.size());
+
+ UserPoint *v = (UserPoint *)&data.mArray[mElement.mVertexOffset];
+ for(int i=0;i &inSubPolys)
{
+ bool showTriangles = false;
+
if (mSolidMode && inOutline.size()<3)
return;
@@ -653,9 +700,12 @@ public:
}
}
if (!isConvex)
+ {
ConvertOutlineToTriangles(inOutline,inSubPolys);
+ //showTriangles = true;
+ }
}
- if (inOutline.size()<3)
+ if (mSolidMode && inOutline.size()<3)
return;
@@ -663,10 +713,18 @@ public:
if (mElement.mSurface)
mElement.mTexOffset = mElement.mVertexOffset + 2*sizeof(float);
- PushVertices(inOutline);
+ if (showTriangles)
+ {
+ PushTriangleWireframe(inOutline);
+ //PushOutline(inOutline);
+ }
+ else
+ {
+ PushVertices(inOutline);
- if (!isConvex)
- data.mElements.last().mPrimType = ptTriangles;
+ if (!isConvex)
+ data.mElements.last().mPrimType = ptTriangles;
+ }
}
@@ -837,7 +895,7 @@ public:
}
- void removeLoops(QuickVec &curve,int startPoint,float turningPoint)
+ void removeLoops(QuickVec &curve,int startPoint,float turningPoint,int *inAdjustStart=0)
{
for(int i=startPoint;ii)
+ (*inAdjustStart)--;
curve.erase(i,1);
i--;
continue;
@@ -905,6 +965,12 @@ public:
// replace c[i+1] with p, and erase upto and including c[j]
p1 = p;
curve.EraseAt(i+2,j+1);
+ if (inAdjustStart)
+ {
+ int &a = *inAdjustStart;
+ if (a>i)
+ a = i;
+ }
break;
}
}
@@ -1212,8 +1278,8 @@ public:
float turnLeft = seg.isCurve() ? segJoinLeft - 0.66 : 0;
float turnRight = seg.isCurve() ? segJoinRight - 0.66 : 0;
- removeLoops(leftCurve,prevSegLeft,turnLeft);
- removeLoops(rightCurve,prevSegRight,turnRight);
+ removeLoops(leftCurve,prevSegLeft,turnLeft,&segStartLeft);
+ removeLoops(rightCurve,prevSegRight,turnRight,&segStartRight);
prevSegLeft = segStartLeft;
prevSegRight = segStartRight;
diff --git a/legacy/project/src/common/Surface.cpp b/legacy/project/src/common/Surface.cpp
index f8fbe577b..468963fc6 100644
--- a/legacy/project/src/common/Surface.cpp
+++ b/legacy/project/src/common/Surface.cpp
@@ -324,7 +324,7 @@ void TTBlit( const DEST &outDest, const SRC &inSrc,const MASK &inMask,
inMask.SetPos(inX , inY + y );
inSrc.SetPos( inSrcRect.x, inSrcRect.y + y );
for(int x=0;x(inMask.Mask(inSrc.Next()));
#else
if (!DEST_ALPHA)
@@ -814,15 +814,16 @@ void SimpleSurface::BlitChannel(const RenderTarget &outTarget, const Rect &inSrc
bool set_255 = (inSrcChannel==CHAN_ALPHA && !(mPixelFormat & pfHasAlpha) );
- // Translate inSrcRect src_rect to dest ...
- Rect src_rect(inPosX,inPosY, inSrcRect.w, inSrcRect.h );
- // clip ...
+ // Start with unclipped dest rect
+ Rect src_rect(inSrcRect.x+inPosX,inSrcRect.x+inPosY, inSrcRect.w, inSrcRect.h );
+ // Clip to dest size...
src_rect = src_rect.Intersect(outTarget.mRect);
- // translate back to source-coordinates ...
- src_rect.Translate(inSrcRect.x-inPosX, inSrcRect.y-inPosY);
- // clip to origial rect...
- src_rect = src_rect.Intersect( inSrcRect );
+ // Translate back to source-coordinates ...
+ src_rect.Translate(-inPosX, -inPosY);
+
+ // Clip to actual source rect...
+ src_rect = src_rect.Intersect( Rect(0,0,Width(),Height() ) );
if (src_rect.HasPixels())
{
diff --git a/legacy/project/src/common/Tessellate.cpp b/legacy/project/src/common/Tessellate.cpp
index 01876314d..169bdfe78 100644
--- a/legacy/project/src/common/Tessellate.cpp
+++ b/legacy/project/src/common/Tessellate.cpp
@@ -1,143 +1,101 @@
#include
#include
#include
+#include
+
+//#define USE_POLY2TRI
+
+#ifdef USE_POLY2TRI
+#include "poly2tri/Poly2Tri.h"
+#endif
namespace nme
{
-struct ConcaveInfo
+const double INSIDE_TOL = 1e-12;
+
+
+
+
+
+struct TriSearch
{
- ConcaveInfo()
+ UserPoint next;
+ UserPoint prev;
+ UserPoint min;
+ UserPoint max;
+ UserPoint p;
+ UserPoint v1;
+ UserPoint v2;
+ double denom;
+ bool isFlat;
+ bool isConcave;
+
+ TriSearch(const UserPoint &inP0, const UserPoint &inPrev, const UserPoint &inNext)
{
- prevConcave = 0;
- nextConcave = 0;
- }
- void init()
- {
- prevConcave = 0;
- nextConcave = 0;
- }
- void makeHead()
- {
- prevConcave = nextConcave = this;
- }
+ p = inP0;
+ next = inNext;
+ prev = inPrev;
+ v1 = next - p;
+ v2 = prev - p;
- ConcaveInfo *prevConcave;
- ConcaveInfo *nextConcave;
-};
+ denom = v1.Cross(v2);
+ isConcave = denom<0;
-struct ConcaveSet
-{
- ConcaveInfo head;
-
- ConcaveSet()
- {
- head.makeHead();
- }
-
- struct iterator
- {
- ConcaveInfo *info;
-
- inline iterator(ConcaveInfo *inInfo) : info(inInfo) { }
- inline void operator++() { info = info->nextConcave; }
- inline bool operator!=(const iterator &inRhs) { return info!=inRhs.info; }
-
- template
- inline T value() { return (T)info; }
- };
-
- void setConcave(ConcaveInfo *info, bool inConcave)
- {
- // Already set?
- if ((bool)(info->nextConcave) == inConcave)
- return;
-
- if (inConcave)
+ if (!isConcave)
{
- info->nextConcave = head.nextConcave;
- head.nextConcave = info;
- info->prevConcave = info->nextConcave->prevConcave;
- info->nextConcave->prevConcave = info;
- }
- else
- {
- info->prevConcave->nextConcave = info->nextConcave;
- info->nextConcave->prevConcave = info->prevConcave;
- info->nextConcave =0;
- info->prevConcave =0;
- }
- }
+ isFlat = denom
- bool isEar(UserPoint next, UserPoint p, UserPoint prev)
- {
- UserPoint v1( next - p );
- UserPoint v2( prev - p );
-
- double denom = v1.Cross(v2);
-
- if (denom==0.0) // flat triangle
- {
- //printf(" -> flat\n");
- return true;
- }
-
- UserPoint min = p;
- if (next.xmax.x) max.x=next.x;
- if (next.y>max.y) max.y=next.y;
- if (prev.x>max.x) max.x=prev.x;
- if (prev.y>max.y) max.y=prev.y;
-
- // TODO - speed this up
- for(ConcaveInfo *info = head.nextConcave; info!=&head; info = info->nextConcave)
- {
- UserPoint &concave = ((T *)info)->p;
- if (concave.xmax.x || concave.y>max.y)
- continue;
-
- UserPoint v( concave - p );
- double a = v.Cross(v2);
- if (a>=0 && a=0.0 && (a+b)=0)
- return false;
+ denom -= INSIDE_TOL;
+
+ min = p;
+ if (next.xmax.x) max.x=next.x;
+ if (next.y>max.y) max.y=next.y;
+ if (prev.x>max.x) max.x=prev.x;
+ if (prev.y>max.y) max.y=prev.y;
}
}
-
- return true;
}
+ inline bool pointInTri(UserPoint concave)
+ {
+ UserPoint v( concave - p );
+ double a = v.Cross(v2);
+ if (a>INSIDE_TOL && aINSIDE_TOL && (a+b)INSIDE_TOL);
+ }
+ return false;
+ }
};
-struct EdgePoint : public ConcaveInfo
+
+
+
+struct EdgePoint
{
UserPoint p;
EdgePoint *prev;
EdgePoint *next;
+ bool isConcave;
void init(const UserPoint &inPoint,EdgePoint *inPrev, EdgePoint *inNext)
{
p = inPoint;
next = inNext;
prev = inPrev;
- ConcaveInfo::init();
+ isConcave = false;
}
- inline bool isConcave() const { return nextConcave; }
void unlink()
{
@@ -145,266 +103,116 @@ struct EdgePoint : public ConcaveInfo
next->prev = prev;
}
- void calcConcave(ConcaveSet &ioConcave)
+ bool calcConcave()
{
- ioConcave.setConcave(this,Cross()>0.0);
+ return (prev->p - p).Cross(next->p - p) > 0.0;
}
-
- double Cross()
- {
- return (prev->p - p).Cross(next->p - p);
- }
-
- //bool convex() { return(Cross()<0.0); }
};
-bool IsEar(ConcaveSet &concaveSet,EdgePoint *pi)
+struct ConcaveSet
{
- if (concaveSet.empty())
- return true;
+ typedef std::multiset PointSet;
+ PointSet points;
- if (pi->isConcave())
- return false;
-
- return concaveSet.isEar(pi->next->p, pi->p, pi->prev->p);
-
-}
-
-bool Intersect(UserPoint dir,UserPoint p0,UserPoint p1)
-{
- // Test for simple overlap first ?
- if (dir==p0 || dir==p1)
- return true;
-
- UserPoint v = p1-p0;
- double denom = dir.Cross(v);
- if (denom==0) // parallel - co-linear or not
+ void add(EdgePoint *edge)
{
- if (p0.Cross(dir)!=0.0) // p0 is not on dir ...
+ edge->isConcave = true;
+ points.insert(edge->p);
+ }
+
+ void remove(EdgePoint *edge)
+ {
+ edge->isConcave = false;
+ points.erase(edge->p);
+ }
+
+ bool isEar(EdgePoint *edge)
+ {
+ if (points.empty())
+ return true;
+
+ if (edge->isConcave)
return false;
- // co-linear - find closest point on +ve direction on line ...
- double b[2];
- if (dir.x==0)
+ TriSearch test(edge->p, edge->prev->p, edge->next->p);
+ if (test.isConcave)
+ return false;
+ if (test.isFlat)
+ return true;
+
+ // TODO - maybe some quadtree style structure
+ PointSet::const_iterator p = points.lower_bound(test.min);
+ PointSet::const_iterator last = points.upper_bound(test.max);
+ for( ; p!=last; ++p )
{
- b[0] = (double)p0.y/(double)dir.y;
- b[1] = (double)p1.y/(double)dir.y;
- }
- else
- {
- b[0] = (double)p0.x/(double)dir.x;
- b[1] = (double)p1.x/(double)dir.x;
+ UserPoint concave = *p;
+ // Y-bounds should be good since they are sorted by Y
+ if (concave.xtest.max.x )
+ continue;
+
+ if (test.pointInTri(concave))
+ return false;
}
- int point;
- if (b[0]>=0 && b[1]>=0)
- point = b[1]=0)
- point = 0;
- else if (b[1]>=0)
- point = 1;
- else
- point = b[1]>b[0];
-
- return(b[point]>=0 && b[point]<=1.0);
+ return true;
}
-
- double beta = p0.Cross(v)/denom;
- if (beta<0.0 || beta>1.0)
- return(false);
-
- // Test alpha ...
- double alpha = p0.Cross(dir)/denom;
- return(alpha>=0 && alpha<=1.0);
-}
-
-bool FindDiag(ConcaveSet &concaveSet,EdgePoint *&p1,EdgePoint *&p2)
-{
- for(ConcaveSet::iterator it = concaveSet.begin(); it!=concaveSet.end(); ++it)
- {
- EdgePoint *p = it.value();
-
- UserPoint corner = p->p;
- UserPoint v1( p->prev->p - corner );
- UserPoint v2( p->next->p - corner );
- for(EdgePoint *other=p->next; ; )
- {
- UserPoint v( other->p-corner );
- double a = v.Cross(v2);
- double b = v1.Cross(v);
- if (a>=0.0 && b>=0.0)
- {
- // Found candidate, check for intersections ...
- EdgePoint *l=p->prev;
- for( ;l!=other->next;l=l->prev)
- if (Intersect(v,l->p-corner,l->prev->p-corner))
- break;
- if (l==other->next)
- {
- EdgePoint *r=p->next;
- for(;l!=other->prev;r=r->next)
- if (Intersect(v,r->p-corner,r->next->p-corner))
- break;
- if (r==other->prev)
- {
- // found !
- p1 = p;
- p2 = other;
- return true;
- }
- }
- }
- other = other->next;
- if (other == p->prev)
- break;
- }
- }
- return(false);
-}
-
+};
void ConvertOutlineToTriangles(EdgePoint *head, int size, Vertices &outTriangles)
{
outTriangles.reserve( outTriangles.size() + (size-2)*3);
- ConcaveSet concaveHead;
+ ConcaveSet concaveSet;
for(EdgePoint *p = head; ; )
{
- p->calcConcave(concaveHead);
+ if (p->calcConcave())
+ concaveSet.add(p);
p = p->next; if (p==head) break;
}
EdgePoint *pi= head;
EdgePoint *p_end = pi->prev;
- while(size>2)
+ while( pi!=p_end && size>2)
{
- while( pi!=p_end && size>2)
+ if ( concaveSet.isEar(pi) )
{
- if ( IsEar(concaveHead,pi) )
- {
- // Have ear triangle - yay - clip it
- outTriangles.push_back(pi->prev->p);
- outTriangles.push_back(pi->p);
- outTriangles.push_back(pi->next->p);
+ // Have ear triangle - yay - clip it
+ outTriangles.push_back(pi->prev->p);
+ outTriangles.push_back(pi->p);
+ outTriangles.push_back(pi->next->p);
- //printf(" ear : %f,%f %f,%f %f,%f\n", pi->prev->p.x, pi->prev->p.y,
- //pi->p.x, pi->p.y,
- //pi->next->p.x, pi->next->p.y );
+ //printf(" ear : %f,%f %f,%f %f,%f\n", pi->prev->p.x, pi->prev->p.y,
+ //pi->p.x, pi->p.y,
+ //pi->next->p.x, pi->next->p.y );
- concaveHead.setConcave(pi,false);
- pi->unlink();
- // Have we become concave or convex ?
- pi->next->calcConcave(concaveHead);
- // Has the previous one become convex ?
- pi->prev->calcConcave(concaveHead);
+ pi->unlink();
- // Take a step back and try again...
- pi = pi->prev;
- p_end = pi->prev;
+ // Has it stopped being concave?
+ if (pi->next->isConcave && !pi->next->calcConcave())
+ concaveSet.remove(pi->next);
+ // Has it stopped being concave?
+ if (pi->prev->isConcave && !pi->prev->calcConcave())
+ concaveSet.remove(pi->prev);
- size --;
- }
- else
- pi = pi->next;
- }
-
- if (size==3)
- {
- /*
- printf("Triangle : %f,%f %f,%f %f,%f\n",
- pi->prev->p.x, pi->prev->p.y,
- pi->p.x, pi->p.y,
- pi->next->p.x, pi->next->p.y );
- */
- break;
- }
- else if (size>2 )
- {
- break;
-
- EdgePoint *b1=0,*b2=0;
- //printf("Diag %d ?\n",size);
- if ( FindDiag(concaveHead,b1,b2))
- {
- // Call recursively...
- /*
- Vertices loop1;
- loop1.reserve(size);
- EdgePoint *p;
- for(p=b1;p!=b2;p=p->next)
- loop1.push_back(p->p);
- loop1.push_back(p->p);
-
- ConvertOutlineToTriangles(loop1,outTriangles);
-
-
- Vertices loop2;
- loop2.reserve(size);
- for(p=b2;p!=b1;p=p->next)
- loop2.push_back(p->p);
- loop2.push_back(p->p);
- ConvertOutlineToTriangles(loop2,outTriangles);
- */
- }
- else
- {
- #if 1
- //printf("No diag?\n");
- break;
- #else
- // Hmmm look for "least concave" point ...
- pi = p0->next->next;
- double best_val = -1e99;
- EdgePoint *least_concave = 0;
- double smallest_val = 1e99;
- EdgePoint *smallest = 0;
- while(pi!=p0)
- {
- if (concave_points.find(pi->prev)!=concave_points.end())
- {
- double cross = pi->Cross();
- if (cross>best_val)
- {
- best_val = cross;
- least_concave = pi;
- }
- }
- else if (!least_concave)
- {
- double cross = pi->Cross();
- if (crossnext;
- }
-
- if (least_concave)
- pi = least_concave;
- else
- pi = smallest;
-
- force_ear = true;
- #endif
- }
+ // Take a step back and try again...
+ pi = pi->prev;
+ p_end = pi->prev;
+
+ size --;
}
+ else
+ pi = pi->next;
}
}
+
+
// --- External interface ----------
-void ReverseSubPoly(UserPoint *ioPtr,int inN)
-{
- int half = inN>>1;
- for(int i=0;ip.x;
for(EdgePoint *in = inInner; ; )
{
- for(EdgePoint *out = inOuter; ; )
+ count++;
+ if (in->p.x < leftX)
{
- double dist = in->p.Dist2(out->p);
- if (distnext; if (out==inOuter) break;
+ leftX = in->p.x;
+ bestIn = in;
}
in = in->next; if (in==inInner) break;
}
+ double leftY = bestIn->p.y;
+
+ // Now, shoot ray left to find outer intersection
+
+ double closestX = -1e39;
+ double bestAlpha = 0.0;
+ EdgePoint *bestOut = 0;
+ EdgePoint *e0 = inOuter;
+ for(EdgePoint *e0 = inOuter; ; )
+ {
+ if ( fabs(e0->p.y-leftY) < 0.0001 )
+ {
+ if (e0->p.x<=leftX && e0->p.x>closestX)
+ {
+ bestOut = e0;
+ closestX = e0->p.x;
+ bestAlpha = 0.0;
+ }
+ }
+ else if ( ( (e0->p.ynext->p.y>leftY) ) ||
+ (e0->p.y>leftY) && (e0->next->p.yp.x < leftX || e0->next->p.xp.y - leftY ) / fabs( e0->p.y - e0->next->p.y);
+ double x = e0->p.x + (e0->next->p.x-e0->p.x) * alpha;
+ if (x<=leftX && x>closestX)
+ {
+ closestX = x;
+ bestOut = e0;
+ bestAlpha = alpha;
+ }
+ }
+ }
+
+ e0 = e0->next;
+ if (e0==inOuter)
+ break;
+ }
+
+ if (!bestOut)
+ {
+ //printf("Could not link hole\n");
+ return 0;
+ }
+
+ if (bestAlpha>0.9999)
+ {
+ bestOut = bestOut->next;
+ }
+ else if (bestAlpha>0.0001)
+ {
+ // Insert node into outline
+ EdgePoint *b = inBuffer + 2;
+ b->init( UserPoint(closestX,bestOut->p.y + ( bestOut->next->p.y- bestOut->p.y) * bestAlpha),
+ bestOut, bestOut->next );
+
+ bestOut->next->prev = b;
+ bestOut->next = b;
+
+ bestOut = b;
+ count ++;
+ }
+
inBuffer[0] = *bestOut;
inBuffer[1] = *bestIn;
@@ -514,29 +385,71 @@ void LinkSubPolys(EdgePoint *inOuter, EdgePoint *inInner, EdgePoint *inBuffer)
bestIn->prev->next = bestIn;
inBuffer[0].prev = bestIn;
inBuffer[0].next->prev = inBuffer;
+
+ return count+2;
}
struct SubInfo
{
- void calcExtent()
+ void set(int inP0, int inSize, UserPoint *inVertices)
{
- x0 = x1 = first->p.x;
- y0 = y1 = first->p.y;
- for(EdgePoint *p = first->next; p!=first; p = p->next )
- {
- if (p->p.x < x0) x0 = p->p.x;
- if (p->p.x > x1) x1 = p->p.x;
- if (p->p.y < y0) y0 = p->p.y;
- if (p->p.y > y1) y1 = p->p.y;
- }
+ p0 = inP0;
+ size = inSize;
+ vertices = inVertices + p0;
+
+ x0 = x1 = vertices[0].x;
+ y0 = y1 = vertices[0].y;
+ for(int i=1;i x1) x1 = p.x;
+ if (p.y < y0) y0 = p.y;
+ if (p.y > y1) y1 = p.y;
+ }
}
- bool contains(UserPoint inP)
+
+ bool operator <(const SubInfo &inOther) const
+ {
+ // Extents not overlap - call it even
+ if (x1 <= inOther.x0 || x0>=inOther.x1 || y1 <= inOther.y0 || y0>=inOther.y1 )
+ return false;
+
+ bool allOtherInExtent = true;
+ for(int i=0;i=x0 && inP.x<=x1 && inP.y>=y0 && inP.y<=y1;
}
+ UserPoint *vertices;
EdgePoint *first;
- EdgePoint link[2];
+ EdgePoint link[3];
int group;
bool is_internal;
int p0;
@@ -545,6 +458,11 @@ struct SubInfo
float y0,y1;
};
+bool sortLeft(SubInfo *a, SubInfo *b)
+{
+ return a->x0 < b->x0;
+}
+
void ConvertOutlineToTriangles(Vertices &ioOutline,const QuickVec &inSubPolys)
{
// Order polygons ...
@@ -552,22 +470,33 @@ void ConvertOutlineToTriangles(Vertices &ioOutline,const QuickVec &inSubPol
if (subs<1)
return;
- QuickVec subInfo;
+ QuickVec subInfo(subs);
+ int bigSubs = 0;
+ int p0 = 0;
+ for(int i=0;i2 && ioOutline[p0] == ioOutline[p0+size-1])
+ size--;
+
+ if (size>2)
+ subInfo[bigSubs++].set(p0,size, &ioOutline[0]);
+
+ p0 = inSubPolys[i];
+ }
+ subInfo.resize(subs=bigSubs);
+ std::sort(subInfo.begin(), subInfo.end());
+
+
+
QuickVec edges(ioOutline.size());
int index = 0;
int groupId = 0;
for(int sub=0;sub0?inSubPolys[sub-1]:0;
- info.size = inSubPolys[sub] - info.p0;
- if (ioOutline[info.p0] == ioOutline[info.p0+info.size-1])
- info.size--;
-
- if (info.size>2)
- {
UserPoint *p = &ioOutline[info.p0];
double area = 0.0;
for(int i=2;i &inSubPol
bool reverse = area < 0;
int parent = -1;
- for(int prev=subInfo.size()-1; prev>=0 && parent==-1; prev--)
+ for(int prev=sub-1; prev>=0 && parent==-1; prev--)
{
if (subInfo[prev].contains(p[0]))
{
@@ -608,19 +537,17 @@ void ConvertOutlineToTriangles(Vertices &ioOutline,const QuickVec &inSubPol
info.first = &edges[index];
AddSubPoly(info.first,p,info.size,reverse!=info.is_internal);
- if (sub holes;
for(int sub=0;sub &inSubPol
if (first<0)
{
first = sub;
- size = info.size;
+ totalSize = size = info.size;
}
else
{
- LinkSubPolys(subInfo[first].first,info.first, info.link);
- size += info.size + 2;
+ totalSize += info.size;
+ holes.push_back(&info);
}
}
}
if (first>=0)
- ConvertOutlineToTriangles(subInfo[first].first, size,triangles);
+ {
+ int holeCount = holes.size();
+
+ #ifdef USE_POLY2TRI
+ p2t::Poly2Tri *poly2Tri = p2t::Poly2Tri::create();
+
+ std::vector< p2t::Point> pointBuffer(totalSize);
+ UserPoint *p = subInfo[first].vertices;
+ int p0 = 0;
+ for(int i=0;iAddSubPoly(&pointBuffer[0],size);
+ p0 += size;
+
+ for(int h=0;hAddSubPoly(&pointBuffer[p0],size);
+ p0 += size;
+ }
+
+ const std::vector< p2t::Triangle* > &tris = poly2Tri->Triangulate();
+
+ for(int i=0;iGetPoint(0) );
+ triangles.push_back( *tri->GetPoint(1) );
+ triangles.push_back( *tri->GetPoint(2) );
+ }
+
+ delete poly2Tri;
+
+ #else
+ if (holeCount)
+ {
+ std::sort(holes.begin(), holes.end(), sortLeft);
+
+ for(int h=0;h
#include
#include
+#include
#ifndef iswalpha
#define iswalpha isalpha
@@ -18,6 +19,8 @@ namespace nme
int gPasswordChar = 42; // *
+static const double GAP = 2.0;
+
TextField::TextField(bool inInitRef) : DisplayObject(inInitRef),
alwaysShowSelection(false),
antiAliasType(aaNormal),
@@ -49,27 +52,32 @@ TextField::TextField(bool inInitRef) : DisplayObject(inInitRef),
mStringState = ssText;
mLinesDirty = true;
mGfxDirty = true;
- boundsWidth = 100.0;
- boundsHeight = 100.0;
- mActiveRect = Rect(100,100);
+ mTilesDirty = false;
+ mCaretDirty = true;
+ fieldWidth = 100.0;
+ explicitWidth = fieldWidth;
+ fieldHeight = 100.0;
+ //mActiveRect = Rect(100,100);
mFontsDirty = false;
mSelectMin = mSelectMax = 0;
mSelectDownChar = 0;
caretIndex = 0;
mCaretGfx = 0;
mHighlightGfx = 0;
- mLastCaretHeight = -1;
+ mTiles = 0;
mSelectKeyDown = -1;
maxScrollH = 0;
maxScrollV = 1;
setText(L"");
textWidth = 0;
textHeight = 0;
+ fontScale = 1.0;
+ fontToLocal = 1.0;
mLastUpDownX = -1;
- mLayoutScaleH = mLayoutScaleV = -1.0;
- mLayoutRotation = gr0;
needsSoftKeyboard = true;
mHasCaret = false;
+ screenGrid = false;
+ mBlink0 = GetTimeStamp();
}
TextField::~TextField()
@@ -78,67 +86,70 @@ TextField::~TextField()
mCaretGfx->DecRef();
if (mHighlightGfx)
mHighlightGfx->DecRef();
+ if (mTiles)
+ mTiles->DecRef();
defaultTextFormat->DecRef();
mCharGroups.DeleteAll();
}
-void TextField::setWidth(double inWidth)
-{
- boundsWidth = inWidth;
- mLinesDirty = true;
- mGfxDirty = true;
-}
-
double TextField::getWidth()
{
- /*if (autoSize != asNone)
- {
- if (mLinesDirty)
- Layout();
- return textWidth;
- }
- return boundsWidth;*/
- Transform trans;
- trans.mMatrix = &GetLocalMatrix();
- Extent2DF ext;
- GetExtent(trans,ext,false,true);
+ if (mLinesDirty)
+ Layout();
- if (!ext.Valid())
- {
- return 0;
- }
-
- return ext.Width();
+ return fieldWidth*scaleX;
}
double TextField::getHeight()
{
- /*if (autoSize != asNone)
- {
- if (mLinesDirty)
- Layout();
- return textHeight;
- }
- return boundsHeight;*/
- Transform trans;
- trans.mMatrix = &GetLocalMatrix();
- Extent2DF ext;
- GetExtent(trans,ext,false,true);
- if (!ext.Valid())
- return 0;
+ if (mLinesDirty)
+ Layout();
- return ext.Height();
+ return fieldHeight*scaleY;
}
-
+void TextField::setWidth(double inWidth)
+{
+ explicitWidth = inWidth;
+ if (autoSize==asNone || wordWrap)
+ {
+ if (scaleX!=0)
+ fieldWidth = inWidth/scaleX;
+ else
+ fieldWidth = 0.0;
+ mLinesDirty = true;
+ mGfxDirty = true;
+ }
+ mDirtyFlags |= dirtLocalMatrix;
+}
void TextField::setHeight(double inHeight)
{
- boundsHeight = inHeight;
- mLinesDirty = true;
- mGfxDirty = true;
+ if (autoSize==asNone)
+ {
+ if (scaleY!=0)
+ fieldHeight = inHeight/scaleY;
+ else
+ fieldHeight = 0.0;
+
+ fieldHeight = inHeight;
+ mLinesDirty = true;
+ mGfxDirty = true;
+ }
}
+void TextField::modifyLocalMatrix(Matrix &ioMatrix)
+{
+ if ( (autoSize==asCenter || autoSize==asRight) && !multiline )
+ {
+ if (autoSize==asCenter)
+ ioMatrix.mtx -= (fieldWidth-explicitWidth) * 0.5;
+ else
+ ioMatrix.mtx -= (fieldWidth-explicitWidth);
+ }
+}
+
+
const TextFormat *TextField::getDefaultTextFormat()
{
@@ -178,12 +189,12 @@ void TextField::SplitGroup(int inGroup,int inPos)
TextFormat *TextField::getTextFormat(int inStart,int inEnd)
{
TextFormat *commonFormat = NULL;
-
+
for(int i=0;imFormat;
-
+
if (commonFormat == NULL)
{
commonFormat = new TextFormat (*format);
@@ -234,21 +245,21 @@ void TextField::setTextFormat(TextFormat *inFmt,int inStart,int inEnd)
{
if (!inFmt)
return;
-
+
Layout();
-
+
int max = mCharPos.size();
-
+
if (inStart<0)
{
inStart = 0;
- inEnd = max;
+ inEnd = max;
}
else if (inEnd<0)
{
inEnd = inStart + 1;
}
-
+
if (inEnd>max) inEnd = max;
if (inEnd<=inStart)
@@ -298,6 +309,8 @@ void TextField::setTextColor(int inCol)
defaultTextFormat = defaultTextFormat->COW();
defaultTextFormat->color = inCol;
mGfxDirty = true;
+ mTilesDirty = true;
+ mCaretDirty = true;
DirtyCache();
}
}
@@ -353,24 +366,26 @@ void TextField::setWordWrap(bool inWordWrap)
void TextField::setAutoSize(int inAutoSize)
{
- autoSize = (AutoSizeMode)inAutoSize;
- mLinesDirty = true;
- mGfxDirty = true;
- DirtyCache();
+ if (inAutoSize!=autoSize)
+ {
+ autoSize = (AutoSizeMode)inAutoSize;
+ mLinesDirty = true;
+ mGfxDirty = true;
+ mDirtyFlags |= dirtLocalMatrix;
+ DirtyCache();
+ }
}
double TextField::getTextHeight()
{
Layout();
- double h = textHeight/mLayoutScaleV;
- return std::max(h-4,0.0);
+ return textHeight;
}
double TextField::getTextWidth()
{
Layout();
- double w = textWidth/mLayoutScaleH;
- return std::max(w-4,0.0);
+ return textWidth;
}
@@ -384,8 +399,8 @@ bool TextField::FinishEditOnEnter()
int TextField::getBottomScrollV()
{
Layout();
- int l = std::max(scrollV -1,0);
- int height = boundsHeight;
+ double l = std::max(scrollV -1,0);
+ double height = fieldHeight-2*GAP;
while(height>0 && lmaxScrollH)
scrollH = maxScrollH;
- // TODO: do we need to re-layout on scroll?
- mLinesDirty = true;
- mGfxDirty = true;
- DirtyCache();
+
+ if (oldPos!=scrollH)
+ {
+ mTilesDirty = true;
+ mCaretDirty = true;
+ mGfxDirty = true;
+ DirtyCache();
+ }
}
void TextField::setScrollV(int inScrollV)
{
+ setScrollVClearSel(inScrollV,true);
+}
+
+void TextField::setScrollVClearSel(int inScrollV,bool inClearSel)
+{
+ int oldPos = scrollV;
if (inScrollV<1)
inScrollV = 1;
if (inScrollV>maxScrollV)
inScrollV =maxScrollV;
- if (inScrollV!=scrollV && mSelectMin!=mSelectMax)
+ if (inScrollV!=oldPos)
{
- mSelectMin = mSelectMax = 0;
- mSelectKeyDown = -1;
+ if (inClearSel && mSelectMin!=mSelectMax)
+ {
+ mSelectMin = mSelectMax = 0;
+ mSelectKeyDown = -1;
+ }
+
+ scrollV = inScrollV;
+
+ mTilesDirty = true;
+ mCaretDirty = true;
+ mGfxDirty = true;
+ DirtyCache();
}
-
- scrollV = inScrollV;
- // TODO: do we need to re-layout on scroll?
- mLinesDirty = true;
- mGfxDirty = true;
- DirtyCache();
-
}
-int TextField::getLength()
+int TextField::getLength() const
{
if (mLines.empty()) return 0;
- Line & l = mLines[ mLines.size()-1 ];
+ const Line & l = mLines[ mLines.size()-1 ];
return l.mChar0 + l.mChars;
}
-int TextField::PointToChar(int inX,int inY)
+int TextField::PointToChar(UserPoint inPoint) const
{
- if (mCharPos.empty())
+ if (mCharPos.empty() || inPoint.y inY && line.mChars)
+ const Line &line = mLines[l];
+ //printf("%d] %f/%f/%f\n",l, line.mY0, inPoint.y, line.mY0+line.mMetrics.height );
+ if ( (line.mY0+line.mMetrics.height) > inPoint.y && line.mChars)
{
+ if (line.mChars==1)
+ return line.mChar0;
+
// Find the char
for(int c=0; cinX)
- return c==0 ? line.mChar0 : line.mChar0+c-1;
+ {
+ double nextX = cEnablePopupKeyboard(true);
- UserPoint point = TargetToRect(GetFullMatrix(true), UserPoint( inEvent.x, inEvent.y) );
- int pos = PointToChar(point.x,point.y);
+ UserPoint point = GlobalToLocal(UserPoint( inEvent.x, inEvent.y));
+ int pos = PointToChar(point);
caretIndex = pos;
if (selectable)
{
mSelectDownChar = pos;
mSelectMin = mSelectMax = pos;
+ mTilesDirty = true;
+ mCaretDirty = true;
mGfxDirty = true;
DirtyCache();
}
@@ -501,42 +539,14 @@ bool TextField::CaptureDown(Event &inEvent)
return true;
}
-UserPoint TextField::TargetToRect(const Matrix &inMatrix,const UserPoint &inPoint)
-{
- UserPoint p = (inPoint - UserPoint(inMatrix.mtx, inMatrix.mty));
- switch(mLayoutRotation)
- {
- case gr0: break;
- case gr90: return UserPoint(p.y,-p.x);
- case gr180: return UserPoint(-p.x,-p.y);
- case gr270: return UserPoint(-p.y,p.x);
- }
- return p;
-}
-
-UserPoint TextField::RectToTarget(const Matrix &inMatrix,const UserPoint &inPoint)
-{
- UserPoint trans(inMatrix.mtx, inMatrix.mty);
- switch(mLayoutRotation)
- {
- case gr0: break;
- case gr90: return UserPoint(-inPoint.y,inPoint.x) + trans;
- case gr180: return UserPoint(-inPoint.x,-inPoint.y) + trans;
- case gr270: return UserPoint(inPoint.y,-inPoint.x) + trans;
- }
- return inPoint + trans;
-
-}
-
-
-
void TextField::Drag(Event &inEvent)
{
if (selectable)
{
mSelectKeyDown = -1;
- UserPoint point = TargetToRect(GetFullMatrix(true),UserPoint( inEvent.x, inEvent.y) );
- int pos = PointToChar(point.x,point.y);
+ UserPoint point = GlobalToLocal(UserPoint( inEvent.x, inEvent.y));
+
+ int pos = PointToChar(point);
if (pos>mSelectDownChar)
{
mSelectMin = mSelectDownChar;
@@ -547,22 +557,24 @@ void TextField::Drag(Event &inEvent)
mSelectMin = pos;
mSelectMax = mSelectDownChar;
}
- if (point.x>mActiveRect.x1())
- {
- scrollH+=(point.x-mActiveRect.x1());
- if (scrollH>maxScrollH)
- scrollH = maxScrollH;
- }
- else if (point.xfieldWidth-GAP)
+ setScrollH(scrollH+(point.x-(fieldWidth-GAP)));
+ else if (point.xfieldHeight-GAP)
+ setScrollVClearSel(scrollV+1,false);
+ else if (point.y %d,%d\n", pos, mSelectDownChar, mSelectMin , mSelectMax);
mGfxDirty = true;
+ mTilesDirty = true;
+ mCaretDirty = true;
DirtyCache();
}
}
@@ -613,7 +625,7 @@ void TextField::OnKey(Event &inEvent)
ShowCaret();
OnChange();
return;
-
+
case keyDELETE:
if (mSelectMin0) caretIndex--; break;
@@ -672,6 +689,8 @@ void TextField::OnKey(Event &inEvent)
mSelectMin = std::min(mSelectKeyDown,caretIndex);
mSelectMax = std::max(mSelectKeyDown,caretIndex);
mGfxDirty = true;
+ mTilesDirty = true;
+ mCaretDirty = true;
}
ShowCaret();
return;
@@ -707,63 +726,48 @@ void TextField::OnKey(Event &inEvent)
void TextField::ShowCaret(bool inFromDrag)
{
- if (!CaretOn())
- return;
- ImagePoint pos(0,0);
- bool changed = false;
+ mCaretDirty = true;
+ mBlink0 = GetTimeStamp();
+ mHasCaret = false;
- if (caretIndex < mCharPos.size())
- pos = mCharPos[caretIndex];
- else if (mLines.size())
+ UserPoint pos = GetCursorPos() - GetScrollPos();
+ // When dragging, allow caret to be hidden off to the left
+ if (pos.xfieldWidth-GAP)
+ setScrollH( scrollH + pos.x - (fieldWidth-GAP) + 1 );
+
+ int line = LineFromChar(caretIndex);
+ if (pos.y= mActiveRect.w)
+ else if (pos.y+mLines[line].mMetrics.height > fieldHeight-GAP)
{
- changed = true;
- scrollH = pos.x - mActiveRect.w + 1;
+ int scroll = scrollV-1;
+ double extra = pos.y+mLines[line].mMetrics.height - (fieldHeight-GAP);
+ while(extra>0 && scroll= mActiveRect.h)
+ {
+ changed = true;
+ scrollV++;
+ }
+ else if (scrollV>1 && pos.ymaxScrollH)
- {
- scrollH = maxScrollH;
- changed = true;
- }
- else if (scrollH<0)
- {
- scrollH = 0;
- changed = true;
- }
-
- if (scrollV<1)
- {
- changed = true;
- scrollV = 1;
- }
-
-
- if (scrollV <= mLines.size())
- {
- if (pos.y-mLines[scrollV-1].mY0 >= mActiveRect.h)
- {
- changed = true;
- scrollV++;
- }
- else if (scrollV>1 && pos.y mSelectMin)
{
mGfxDirty = true;
}
}
+ */
}
@@ -807,7 +814,8 @@ void TextField::Clear()
Cursor TextField::GetCursor()
{
- return selectable ? (Cursor)(curTextSelect0 + mLayoutRotation) : curPointer;
+ // TODO - angle cursor
+ return selectable ? (Cursor)(curTextSelect0) : curPointer;
}
@@ -837,107 +845,107 @@ WString TextField::getHTMLText()
{
WString result;
TextFormat *cacheFormat = NULL;
-
+
bool inAlign = false;
bool inFontTag = false;
bool inBoldTag = false;
bool inItalicTag = false;
bool inUnderlineTag = false;
-
+
for(int i=0;imFormat;
-
- if (format != cacheFormat)
- {
- if (inUnderlineTag && !format->underline)
- {
- result += L"";
- inAlign = false;
- }
-
- if (inItalicTag && !format->italic)
- {
- result += L"";
- inItalicTag = false;
- }
-
- if (inBoldTag && !format->bold)
- {
- result += L"";
- inBoldTag = false;
- }
-
- if (inFontTag && (WString (format->font).compare (cacheFormat->font) != 0 || format->color != cacheFormat->color || format->size != cacheFormat->size))
- {
- result += L"";
- inFontTag = false;
- }
-
- if (inAlign && format->align != cacheFormat->align)
- {
- result += L"
";
- inAlign = false;
- }
- }
-
- if (!inAlign && format->align != tfaLeft)
- {
- result += L"align)
- {
+ CharGroup *charGroup = mCharGroups[i];
+ TextFormat *format = charGroup->mFormat;
+
+ if (format != cacheFormat)
+ {
+ if (inUnderlineTag && !format->underline)
+ {
+ result += L"";
+ inAlign = false;
+ }
+
+ if (inItalicTag && !format->italic)
+ {
+ result += L"";
+ inItalicTag = false;
+ }
+
+ if (inBoldTag && !format->bold)
+ {
+ result += L"";
+ inBoldTag = false;
+ }
+
+ if (inFontTag && (WString (format->font).compare (cacheFormat->font) != 0 || format->color != cacheFormat->color || format->size != cacheFormat->size))
+ {
+ result += L"";
+ inFontTag = false;
+ }
+
+ if (inAlign && format->align != cacheFormat->align)
+ {
+ result += L"
";
+ inAlign = false;
+ }
+ }
+
+ if (!inAlign && format->align != tfaLeft)
+ {
+ result += L"align)
+ {
case tfaLeft: break;
case tfaCenter: result += L"center"; break;
- case tfaRight: result += L"right"; break;
- case tfaJustify: result += L"justify"; break;
- }
-
- result += L"\">";
- inAlign = true;
- }
-
- if (!inFontTag)
- {
- result += L"color);
- result += L"\" face=\"";
- result += format->font;
- result += L"\" size=\"";
- result += IntToWide(format->size);
- result += L"\">";
- inFontTag = true;
- }
-
- if (!inBoldTag && format->bold)
- {
- result += L"";
- inBoldTag = true;
- }
-
- if (!inItalicTag && format->italic)
- {
- result += L"";
- inItalicTag = true;
- }
-
- if (!inUnderlineTag && format->underline)
- {
- result += L"";
- inUnderlineTag = true;
- }
-
- result += WString(charGroup->mString.mPtr, charGroup->Chars());
- cacheFormat = format;
+ case tfaRight: result += L"right"; break;
+ case tfaJustify: result += L"justify"; break;
+ }
+
+ result += L"\">";
+ inAlign = true;
+ }
+
+ if (!inFontTag)
+ {
+ result += L"color);
+ result += L"\" face=\"";
+ result += format->font;
+ result += L"\" size=\"";
+ result += IntToWide(format->size);
+ result += L"\">";
+ inFontTag = true;
+ }
+
+ if (!inBoldTag && format->bold)
+ {
+ result += L"";
+ inBoldTag = true;
+ }
+
+ if (!inItalicTag && format->italic)
+ {
+ result += L"";
+ inItalicTag = true;
+ }
+
+ if (!inUnderlineTag && format->underline)
+ {
+ result += L"";
+ inUnderlineTag = true;
+ }
+
+ result += WString(charGroup->mString.mPtr, charGroup->Chars());
+ cacheFormat = format;
}
-
+
if (inUnderlineTag) result += L"";
if (inItalicTag) result += L"";
if (inBoldTag) result += L"";
if (inFontTag) result += L"";
if (inAlign) result += L"
";
-
+
return result;
}
@@ -1211,17 +1219,19 @@ int TextField::GroupFromChar(int inChar)
-int TextField::EndOfLineX(int inLine)
+double TextField::EndOfLineX(int inLine) const
{
- Line &line = mLines[inLine];
+ const Line &line = mLines[inLine];
+ if (line.mChars==0)
+ return GAP;
return mCharPos[ line.mChar0 ].x + line.mMetrics.width;
}
-int TextField::EndOfCharX(int inChar,int inLine)
+double TextField::EndOfCharX(int inChar,int inLine) const
{
if (inLine<0 || inLine>=mLines.size() || inChar<0 || inChar>=mCharPos.size())
return 0;
- Line &line = mLines[inLine];
+ const Line &line = mLines[inLine];
// Not last character on line?
if (inChar < line.mChar0 + line.mChars -1 )
return mCharPos[inChar+1].x;
@@ -1249,6 +1259,9 @@ WString TextField::getLineText(int inLine)
return L"";
Line &line = mLines[inLine];
+ if (line.mChars==0)
+ return L"";
+
int g0 = GroupFromChar(line.mChar0);
int g1 = GroupFromChar(line.mChar0 + line.mChars-1);
@@ -1283,14 +1296,14 @@ TextLineMetrics *TextField::getLineMetrics(int inLine)
return &line.mMetrics;
}
-ImagePoint TextField::GetScrollPos()
+UserPoint TextField::GetScrollPos() const
{
- return ImagePoint(scrollH,mLines[std::max(0,scrollV-1)].mY0-2);
+ return UserPoint(scrollH,mLines[std::max(0,scrollV-1)].mY0-GAP);
}
-ImagePoint TextField::GetCursorPos()
+UserPoint TextField::GetCursorPos() const
{
- ImagePoint pos(0,0);
+ UserPoint pos(0,0);
if (caretIndex < mCharPos.size())
pos = mCharPos[caretIndex];
else if (mLines.size())
@@ -1301,6 +1314,15 @@ ImagePoint TextField::GetCursorPos()
return pos;
}
+bool TextField::isLineVisible(int inLine) const
+{
+ if (inLinelineStyle(-1);
mHighlightGfx->beginFill( 0x101060, 1);
// Special case of begin/end on same line ...
if (l0==l1)
{
- //printf("HI %dx%d sv=%d (%d,%d) %d\n", pos.x,pos.y, scrollV, scroll.x, scroll.y, mSelectMin);
- mHighlightGfx->drawRect(pos.x,pos.y,x1-pos.x,height);
+ if (isLineVisible(l0))
+ highlightRect(pos.x,pos.y,x1-pos.x,height);
}
else
{
- mHighlightGfx->drawRect(pos.x,pos.y,EndOfLineX(l0)- scroll.x-pos.x,height);
+ if (isLineVisible(l0))
+ highlightRect(pos.x,pos.y,EndOfLineX(l0)- scroll.x-pos.x,height);
+
for(int y=l0+1;ydrawRect(pos.x,pos.y,EndOfLineX(y)-scroll.x-pos.x,line.mMetrics.height);
+ if (isLineVisible(y))
+ {
+ Line &line = mLines[y];
+ pos = mCharPos[line.mChar0]-scroll;
+ highlightRect(pos.x,pos.y,EndOfLineX(y)-scroll.x-pos.x,line.mMetrics.height);
+ }
+ }
+ if (isLineVisible(l1))
+ {
+ Line &line = mLines[l1];
+ pos = mCharPos[line.mChar0]-scroll;
+ highlightRect(pos.x,pos.y,x1-pos.x,line.mMetrics.height);
}
- Line &line = mLines[l1];
- pos = mCharPos[line.mChar0]-scroll;
- mHighlightGfx->drawRect(pos.x,pos.y,x1-pos.x,line.mMetrics.height);
}
}
mGfxDirty = false;
}
}
+void TextField::highlightRect(double x0, double y0, double w, double h)
+{
+ if (x0fieldWidth-GAP)
+ w = fieldWidth-GAP - x0;
+
+ if (w>0)
+ mHighlightGfx->drawRect(x0,y0,w,h);
+}
+
bool TextField::CaretOn()
{
Stage *s = getStage();
- return (s && isInput && s->GetFocusObject()==this && (( (int)(GetTimeStamp()*3)) & 1));
+ return (s && isInput && s->GetFocusObject()==this && !(( (int)((GetTimeStamp()-mBlink0)*3)) & 1));
}
bool TextField::IsCacheDirty()
@@ -1373,6 +1418,14 @@ bool TextField::IsCacheDirty()
}
+void TextField::toScreenGrid(UserPoint &ioPoint, const Matrix &inMatrix)
+{
+ ioPoint.x = floor((ioPoint.x-inMatrix.mtx)*fontScale+0.5)*fontToLocal+inMatrix.mtx;
+ ioPoint.y = floor((ioPoint.y-inMatrix.mty)*fontScale+0.5)*fontToLocal+inMatrix.mty;
+}
+
+
+
void TextField::Render( const RenderTarget &inTarget, const RenderState &inState )
{
@@ -1383,8 +1436,8 @@ void TextField::Render( const RenderTarget &inTarget, const RenderState &inState
RenderState state(inState);
- Rect r = mActiveRect.Rotated(mLayoutRotation).Translated(matrix.mtx,matrix.mty).RemoveBorder(2*mLayoutScaleH);
- state.mClipRect = r.Intersect(inState.mClipRect);
+ //Rect r = mActiveRect.Rotated(mLayoutRotation).Translated(matrix.mtx,matrix.mty).RemoveBorder(2*mLayoutScaleH);
+ //state.mClipRect = r.Intersect(inState.mClipRect);
if (inState.mMask)
state.mClipRect = inState.mClipRect.Intersect(
@@ -1406,8 +1459,9 @@ void TextField::Render( const RenderTarget &inTarget, const RenderState &inState
RenderState state(inState);
- Rect r = mActiveRect.Rotated(mLayoutRotation).Translated(matrix.mtx,matrix.mty).RemoveBorder(2*mLayoutScaleH);
- state.mClipRect = r.Intersect(inState.mClipRect);
+ // TODO - full transform
+ //Rect r = mActiveRect.Translated(matrix.mtx,matrix.mty).RemoveBorder(2*mLayoutScaleH);
+ //state.mClipRect = r.Intersect(inState.mClipRect);
if (inState.mMask)
state.mClipRect = inState.mClipRect.Intersect(
@@ -1420,13 +1474,13 @@ void TextField::Render( const RenderTarget &inTarget, const RenderState &inState
if (inState.mPhase==rpHitTest)
{
// Convert destination pixels to local pixels...
- UserPoint pos = TargetToRect(matrix,UserPoint(inState.mClipRect.x, inState.mClipRect.y) );
- if ( mActiveRect.Contains(pos) )
+ UserPoint pos = GlobalToLocal(UserPoint(inState.mClipRect.x, inState.mClipRect.y));
+ if (pos.x>=0 && pos.y>=0 && pos.x<=fieldWidth && pos.y<=fieldHeight)
inState.mHitResult = this;
return;
}
- ImagePoint scroll = GetScrollPos();
+ UserPoint scroll = GetScrollPos();
BuildBackground();
@@ -1435,144 +1489,180 @@ void TextField::Render( const RenderTarget &inTarget, const RenderState &inState
if (!gfx.empty())
gfx.Render(inTarget,inState);
- UserPoint origin = RectToTarget( matrix, UserPoint(mActiveRect.x, mActiveRect.y) );
- UserPoint dPdX(1,0);
- UserPoint dPdY(0,1);
- switch(mLayoutRotation)
- {
- case gr0: break;
- case gr90: dPdX = UserPoint(0,1); dPdY = UserPoint(-1,0); break;
- case gr180: dPdX = UserPoint(-1,0); dPdY = UserPoint(0,-1); break;
- case gr270: dPdX = UserPoint(0,-1); dPdY = UserPoint(1,0); break;
- }
-
bool highlight = mHighlightGfx && !mHighlightGfx->empty();
bool caret = CaretOn();
- // Setup matrix for going from Rect to Target
- Matrix rect_to_target;
- if (highlight || caret)
+ if (highlight)
+ mHighlightGfx->Render(inTarget,state);
+
+ if (caret && mCaretDirty)
{
- rect_to_target.m00 = dPdX.x;
- rect_to_target.m01 = dPdY.x;
- rect_to_target.mtx = origin.x;
- rect_to_target.m10 = dPdX.y;
- rect_to_target.m11 = dPdY.y;
- rect_to_target.mty = origin.y;
- state.mTransform.mMatrix = &rect_to_target;
+ mCaretDirty = false;
+ if (!mCaretGfx)
+ mCaretGfx = new Graphics(this,true);
+ else
+ mCaretGfx->clear();
- if (highlight)
- mHighlightGfx->Render(inTarget,state);
-
- if (caret)
+ int line = LineFromChar(caretIndex);
+ if (line>=0)
{
- if (!mCaretGfx)
- mCaretGfx = new Graphics(this,true);
- int line = LineFromChar(caretIndex);
- if (line>=0)
+ UserPoint pos = GetCursorPos() - scroll;
+ if (pos.x>=GAP-1 && pos.x<=fieldWidth-GAP+1 && pos.y>=GAP-1)
{
- int height = mLines[line].mMetrics.height;
- if (height!=mLastCaretHeight)
+ double height = mLines[line].mMetrics.height;
+ if (pos.y+height <= fieldHeight-GAP+1)
{
- mLastCaretHeight = height;
- mCaretGfx->clear();
- mCaretGfx->lineStyle(1,0x000000);
- mCaretGfx->moveTo(0,0);
- mCaretGfx->lineTo(0,mLastCaretHeight);
+ mCaretGfx->lineStyle(1, 0x000000 ,1.0, false, ssmOpenGL );
+ mCaretGfx->moveTo(pos.x,pos.y);
+ mCaretGfx->lineTo(pos.x,pos.y+height);
}
-
- ImagePoint pos = GetCursorPos() - scroll;
-
- rect_to_target.TranslateData(pos.x,pos.y);
- mCaretGfx->Render(inTarget,state);
}
}
}
mHasCaret = caret;
-
- HardwareRenderer *hardware = inTarget.IsHardware() ? inTarget.mHardware : 0;
-
- RenderTarget clipped;
- if (hardware)
- hardware->SetViewport(state.mClipRect);
- else
- clipped = inTarget.ClipRect( state.mClipRect );
-
-
- int line = 0;
- int last_line = mLines.size()-1;
- Surface *hardwareSurface = 0;
- uint32 hardwareTint = 0;
- for(int g=0;gTransform(group.mFormat->color(textColor) | 0xff000000);
- for(int c=0;cDecRef();
+ mTiles = 0;
+ }
+ }
+ else
+ {
+ if (!mTiles)
+ mTiles = new Graphics(this,true);
+ else
+ mTiles->clear();
+
+ int line = 0;
+ int last_line = mLines.size()-1;
+ Surface *fontSurface = 0;
+ uint32 hardwareTint = 0;
+ double clipRight = fieldWidth-GAP;
+
+ float white[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+ float groupColour[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
+ float trans_2x2[4] = { fontToLocal, 0.0f, 0.0f, fontToLocal };
+ for(int g=0;gmActiveRect.h) break;
- while(line= cid)
- line++;
- pos.y += mLines[line].mMetrics.ascent;
-
- int a;
- Tile tile = group.mFont->GetGlyph( ch, a);
- UserPoint p = origin + dPdX*pos.x + dPdY*pos.y+ UserPoint(tile.mOx,tile.mOy);
- uint32 tint = cid>=mSelectMin && cidcolor(textColor);
+ groupColour[0] = tint.getRedFloat();
+ groupColour[1] = tint.getGreenFloat();
+ groupColour[2] = tint.getBlueFloat();
+ groupColour[3] = 1.0;
+ for(int c=0;cEndBitmapRender();
+ int cid = group.mChar0 + c;
+ UserPoint pos = mCharPos[cid]-scroll;
+ if (pos.x < clipRight)
+ {
+ while(line= cid)
+ line++;
+ double lineY = pos.y + mLines[line].mMetrics.ascent;
+ if (lineY>fieldHeight)
+ break;
+ if (pos.y>=GAP)
+ {
+ pos.y = lineY;
- hardwareSurface = tile.mSurface;
- hardwareTint = tint;
- hardware->BeginBitmapRender(tile.mSurface,tint);
+ int a;
+ Tile tile = group.mFont->GetGlyph( ch, a);
+
+ if (fontSurface!=tile.mSurface)
+ {
+ //if (fontSurface) mTiles->endTiles();
+ fontSurface = tile.mSurface;
+ mTiles->beginTiles(fontSurface,!screenGrid,bmNormal);
+ }
+
+ UserPoint p(pos.x+tile.mOx*fontToLocal,pos.y+tile.mOy*fontToLocal);
+ if (screenGrid)
+ {
+ toScreenGrid(p,matrix);
+ }
+
+ double right = p.x+tile.mRect.w*fontToLocal;
+ if (right>GAP)
+ {
+ float *tint = cid>=mSelectMin && cidclipRight)
+ {
+ r.w = (clipRight-GAP)*fontScale + 0.001;
+ if (r.w>0)
+ mTiles->tile(GAP,p.y,r,trans_2x2,tint);
+ }
+ else
+ {
+ mTiles->tile(GAP,p.y,r,trans_2x2,tint);
+ }
+
+ }
+ else if (right>clipRight)
+ {
+ Rect r = tile.mRect;
+ r.w = (clipRight-p.x)*fontScale + 0.001;
+ if (r.w>0)
+ mTiles->tile(p.x,p.y,r,trans_2x2,tint);
+ }
+ else
+ {
+ mTiles->tile(p.x,p.y,tile.mRect,trans_2x2,tint);
+ }
+ }
+ }
+ }
}
- hardware->RenderBitmap(tile.mRect, (int)p.x, (int)p.y);
- }
- else
- {
- tile.mSurface->BlitTo(clipped,
- tile.mRect, (int)p.x, (int)p.y,
- bmTinted, 0,
- (uint32)tint);
}
}
}
}
+
}
+ if (mTiles && !mTiles->empty())
+ mTiles->Render(inTarget,inState);
- if (hardwareSurface)
- hardware->EndBitmapRender();
+ if (caret && mCaretGfx && !mCaretGfx->empty())
+ mCaretGfx->Render(inTarget,state);
}
+
void TextField::GetExtent(const Transform &inTrans, Extent2DF &outExt,bool inForBitmap,bool inIncludeStroke)
{
Layout(*inTrans.mMatrix);
+ /*
if (inForBitmap && !border && !background)
{
- Rect r = mActiveRect.Rotated(mLayoutRotation).
- Translated(inTrans.mMatrix->mtx, inTrans.mMatrix->mty);
+ Rect r = mActiveRect.Translated(inTrans.mMatrix->mtx, inTrans.mMatrix->mty);
for(int corner=0;corner<4;corner++)
outExt.Add( UserPoint(((corner & 1) ? r.x : r.x1()),((corner & 1) ? r.y : r.y1())));
}
- else if (inForBitmap && border)
+ else
+ */
+ if (inForBitmap && border)
{
BuildBackground();
return DisplayObject::GetExtent(inTrans,outExt,inForBitmap,inIncludeStroke);
@@ -1581,11 +1671,10 @@ void TextField::GetExtent(const Transform &inTrans, Extent2DF &outExt,bool inFor
{
for(int corner=0;corner<4;corner++)
{
- //UserPoint pos((corner & 1) ? boundsWidth*mLayoutScaleH : 0,
- // (corner & 2) ? boundsHeight*mLayoutScaleV : 0);
- UserPoint pos((corner & 1) ? mActiveRect.x1() : mActiveRect.x,
- (corner & 2) ? mActiveRect.y1() : mActiveRect.y);
- outExt.Add( RectToTarget(*inTrans.mMatrix,pos) );
+ UserPoint pos((corner & 1) ? fieldWidth : 0, (corner & 2) ? fieldHeight: 0);
+ //UserPoint pos((corner & 1) ? mActiveRect.x1() : mActiveRect.x,
+ // (corner & 2) ? mActiveRect.y1() : mActiveRect.y);
+ outExt.Add( inTrans.mMatrix->Apply(pos.x,pos.y) );
}
}
}
@@ -1626,6 +1715,17 @@ void TextField::DeleteChars(int inFirst,int inEnd)
}
}
+void TextField::ClearSelection()
+{
+ if (mSelectMin!=mSelectMax)
+ {
+ mSelectMin = mSelectMax = 0;
+ mTilesDirty = true;
+ mCaretDirty = true;
+ mGfxDirty = true;
+ }
+}
+
void TextField::DeleteSelection()
{
if (mSelectMin>=mSelectMax)
@@ -1634,12 +1734,15 @@ void TextField::DeleteSelection()
caretIndex = mSelectMin;
mSelectMin = mSelectMax = 0;
mSelectKeyDown = -1;
+ mTilesDirty = true;
+ mCaretDirty = true;
mGfxDirty = true;
}
void TextField::InsertString(WString &inString)
{
- if (caretIndex<0) caretIndex = 0;
+ if (caretIndex<0)
+ caretIndex = 0;
caretIndex = std::min(caretIndex,getLength());
if (maxChars>0)
@@ -1674,74 +1777,68 @@ void TextField::InsertString(WString &inString)
Layout(GetFullMatrix(true));
}
+#ifdef EPPC
+ #define iswspace(x) isspace(x)
+#endif
+
+
static bool IsWord(int inCh)
{
- #ifdef EPPC
- return (!isspace(inCh));
- #else
- return (!iswspace(inCh));
- #endif
//return inCh<255 && (iswalpha(inCh) || isdigit(inCh) || inCh=='_');
-}
-
-static inline int Round6(int inX6)
-{
- return (inX6 + (1<<6) -1) >> 6;
+ // TODO - other breaks?
+ return !iswspace(inCh) && inCh!='-';
}
// Combine x,y scaling with rotation to calculate pixel coordinates for
// each character.
void TextField::Layout(const Matrix &inMatrix)
{
- GlyphRotation rot;
- double scale_h;
- double scale_v;
+ //double scale = scaleY<=0 ? 0.0 : sqrt( inMatrix.m10*inMatrix.m10 + inMatrix.m11*inMatrix.m11 )/scaleY;
+ double scale = sqrt( inMatrix.m10*inMatrix.m10 + inMatrix.m11*inMatrix.m11 );
+ bool grid = ( fabs(fabs(inMatrix.m10)-fabs(inMatrix.m10)))<0.0001 &&
+ fabs(fabs(inMatrix.m00)-fabs(inMatrix.m11))<0.0001 &&
+ ( fabs(inMatrix.m10)<0.0001 || fabs(inMatrix.m11)<0.0001);
- if (fabs(inMatrix.m00)> fabs(inMatrix.m01))
- {
- scale_h = fabs(inMatrix.m00);
- scale_v = fabs(inMatrix.m11);
- rot = inMatrix.m00 < 0 ? gr180 : gr0;
- }
- else
- {
- scale_h = fabs(inMatrix.m10);
- scale_v = fabs(inMatrix.m01);
- rot = inMatrix.m01 < 0 ? gr90 : gr270;
- }
-
-
- if (mFontsDirty || scale_h!=mLayoutScaleH || scale_v!=mLayoutScaleV ||
- rot!=mLayoutRotation)
+ if (mFontsDirty || fabs(scale-fontScale)>0.0001 || grid!=screenGrid)
{
+ // fontScale is local-to-pixel scale
+ fontScale = scale;
+ screenGrid = grid;
for(int i=0;iUpdateFont(scale_v,rot,!embedFonts);
+ mCharGroups[i]->UpdateFont(fontScale,!embedFonts);
+
mLinesDirty = true;
mFontsDirty = false;
- mLayoutScaleV = scale_v;
- mLayoutScaleH = scale_h;
- mLayoutRotation = rot;
+ fontToLocal = scale>0 ? 1.0/scale : 0.0;
}
if (!mLinesDirty)
return;
- //printf("Re-layout\n");
- // Now, layout into local co-ordinates...
+ double font6ToLocalX = fontToLocal/64.0;
+
mLines.resize(0);
mCharPos.resize(0);
- int gap = (int)(2.0*mLayoutScaleH+0.5);
+ if (scaleX==0 || scaleY==0)
+ return;
+
+
+ double oldW = fieldWidth;
+ double oldH = fieldHeight;
+
Line line;
int char_count = 0;
+ double charX = 0;
+ double charY = 0;
+ line.mY0 = charY;
+ mLastUpDownX = -1;
textHeight = 0;
textWidth = 0;
- int x6 = gap << 6;
- int y = gap;
- line.mY0 = y;
- mLastUpDownX = -1;
- int max_x = boundsWidth * mLayoutScaleH - gap;
- if (max_x<1) max_x = 1;
+ double max_x = autoSize!=asNone && !wordWrap ? 1e30 : fieldWidth - GAP*2.0;
+ if (max_x<1)
+ max_x = 1;
+ bool endsWidthNewLine = false;
for(int i=0;i>6,y) );
+ mCharPos.push_back( UserPoint(charX,charY) );
line.mChars++;
char_count++;
cid++;
+
if (!displayAsPassword && !iswalpha(ch) && !isdigit(ch) && ch!='_' && ch!=';' && ch!='.' && ch!=',' && ch!='"' && ch!=':' && ch!='\'' && ch!='!' && ch!='?')
{
- if (!IsWord(ch) || (line.mChars>2 && !IsWord(g.mString[cid-2])) )
+ if (!IsWord(ch) || (cid>=2 && !IsWord(g.mString[cid-2])) )
{
- #ifdef EPPC
- if ( (ch<255 && isspace(ch)) || line.mChars==1)
- #else
- if ( (ch<255 && iswspace(ch)) || line.mChars==1)
- #endif
+ if ( (ch<255 && !IsWord(ch)) || line.mChars==1)
{
last_word_cid = cid;
last_word_line_chars = line.mChars;
@@ -1791,30 +1887,34 @@ void TextField::Layout(const Matrix &inMatrix)
last_word_cid = cid-1;
last_word_line_chars = line.mChars-1;
}
- last_word_x6 = x6;
+ last_word_x = charX;
}
-
+
if (ch=='\n' || ch=='\r')
{
// New line ...
+ line.mMetrics.fontToLocal(fontToLocal);
+ if (i+1leading;
+ charY += line.mMetrics.height;
mLines.push_back(line);
line.Clear();
- g.UpdateMetrics(line.mMetrics);
- y += g.Height() + g.mFormat->leading + 1;
+ endsWidthNewLine = true;
continue;
}
}
-
- int ox6 = x6;
+
+ double ox = charX;
if (displayAsPassword)
ch = gPasswordChar;
if (g.mFont)
- g.mFont->GetGlyph( ch, advance );
+ g.mFont->GetGlyph( ch, advance6 );
else
- advance = 0;
- x6 += advance;
- //printf(" Char %c (%d..%d/%d,%d) %p\n", ch, ox, x, max_x, y, g.mFont);
- if ( !displayAsPassword && (wordWrap) && Round6(x6) > max_x && line.mChars>1)
+ advance6 = 0;
+ charX += advance6*font6ToLocalX;
+
+ //printf(" Char %c (%d..%d/%d,%d) %p\n", ch, ox, x, max_x, charY, g.mFont);
+ if ( !displayAsPassword && (wordWrap) && charX > max_x && line.mChars>1)
{
// No break on line so far - just back up 1 character....
if (last_word_line_chars==0 || !wordWrap)
@@ -1823,7 +1923,7 @@ void TextField::Layout(const Matrix &inMatrix)
line.mChars--;
char_count--;
mCharPos.qpop();
- line.mMetrics.width = Round6(ox6);
+ line.mMetrics.width = ox;
}
else
{
@@ -1832,78 +1932,80 @@ void TextField::Layout(const Matrix &inMatrix)
char_count-= line.mChars - last_word_line_chars;
mCharPos.resize(char_count);
line.mChars = last_word_line_chars;
- line.mMetrics.width = Round6(last_word_x6);
+ line.mMetrics.width = last_word_x;
}
+ line.mMetrics.fontToLocal(fontToLocal);
+ if (i+1leading;
+ charY += line.mMetrics.height;
+ charX = 0;
mLines.push_back(line);
- y += g.Height() + g.mFormat->leading + 1;
- x6 = gap<<6;
line.Clear();
g.UpdateMetrics(line.mMetrics);
continue;
}
- int x = Round6(x6);
- line.mMetrics.width = x;
- if (x>textWidth)
- textWidth = x;
+ double right = charX;
+ if (screenGrid)
+ right = ((int)((right*fontScale+0.999)))*fontToLocal;
+ line.mMetrics.width = right;
+ if (right>textWidth)
+ textWidth = right;
}
}
- textWidth += gap;
- if (line.mChars || mLines.empty())
+
+ if ((endsWidthNewLine && multiline) || line.mChars || mLines.empty())
{
- mCharGroups[mCharGroups.size()-1]->UpdateMetrics(line.mMetrics);
- y += line.mMetrics.height;
+ CharGroup *last=mCharGroups[mCharGroups.size()-1];
+ last->UpdateMetrics(line.mMetrics);
+ line.mMetrics.fontToLocal(fontToLocal);
+ if (endsWidthNewLine)
+ {
+ line.mY0 = charY;
+ line.mChar0 = char_count;
+ line.mChars = 0;
+ line.mCharGroup0 = mCharGroups.size()-1;
+ line.mCharInGroup0 = last->mString.size();
+ }
+ charY += line.mMetrics.height;
mLines.push_back(line);
}
- textHeight = y + gap;
-
- int max_y = boundsHeight * mLayoutScaleV;
- if (autoSize != asNone)
+ textHeight = charY;
+ //printf("textHeight = %f\n", textHeight);
+ if (autoSize!=asNone)
{
- //if (!wordWrap) - still use this, even if wordWrap
+ if (!wordWrap)
{
- switch(autoSize)
- {
- case asNone: break;
- case asLeft: mActiveRect.w = textWidth;
- break;
- case asRight: mActiveRect.x = mActiveRect.x1()-textWidth - gap;
- mActiveRect.w = textWidth;
- break;
- case asCenter: mActiveRect.x = (mActiveRect.x+mActiveRect.x1()-textWidth)/2;
- mActiveRect.w = textWidth;
- break;
- }
- if (autoSize!=asNone)
- {
- boundsHeight = textHeight/mLayoutScaleV;
- }
+ fieldWidth = textWidth + 2.0*GAP;
+ if (screenGrid)
+ fieldWidth += 1;
}
- max_y = mActiveRect.h = textHeight;
+ fieldHeight = textHeight + 2.0*GAP;
+ if (screenGrid)
+ fieldHeight += 1;
}
- else
- mActiveRect = Rect(0,0,boundsWidth*mLayoutScaleH+0.99,boundsHeight*mLayoutScaleV+0.99);
- maxScrollH = std::max(0,textWidth-max_x);
+ maxScrollH = std::max(0.0,textWidth-(fieldWidth-GAP*2));
maxScrollV = 1;
// Work out how many lines from the end fit in the rect, and
// therefore how many lines we can scroll...
- if (textHeight>max_y && mLines.size()>1)
+ double clippedHeight = fieldHeight - 2.0*GAP;
+ int last = mLines.size()-1;
+ if (textHeight>fieldHeight && mLines.size()>1)
{
- int window_height = max_y-3*gap;
- int line = mLines.size()-1;
- int lines_height = mLines[line].mMetrics.height;
- while( line < window_height && line>0 )
+ int lines_visible = 0;
+ double lines_height = mLines[last-lines_visible].mMetrics.height;
+ lines_visible++;
+
+ while( lines_visible window_height)
- break;
- lines_height += mLines[--line].mMetrics.height;
+ lines_height += mLines[last-lines_visible].mMetrics.height;
+ lines_visible++;
}
- maxScrollV = line+1;
+ maxScrollV = mLines.size() - lines_visible + 1;
}
// Align rows ...
@@ -1916,23 +2018,35 @@ void TextField::Layout(const Matrix &inMatrix)
CharGroup &group = *mCharGroups[line.mCharGroup0];
// Get alignment...
- int extra = (mActiveRect.w - line.mMetrics.width - 1);
+ double extra = (fieldWidth - line.mMetrics.width);
switch(group.mFormat->align(tfaLeft))
{
- case tfaJustify: break;
- case tfaRight: break;
- case tfaLeft: extra = 0; break;
- case tfaCenter: extra/=2; break;
+ case tfaJustify:
+ case tfaRight:
+ extra -= GAP;
+ break;
+ case tfaLeft:
+ extra = GAP;
+ break;
+ case tfaCenter:
+ extra*=0.5;
+ break;
}
- if (extra>0)
- {
+ if (extra)
for(int c=0; cDecRef();
}
-bool CharGroup::UpdateFont(double inScale,GlyphRotation inRotation,bool inNative)
+bool CharGroup::UpdateFont(double inScale,bool inNative)
{
int h = 0.5 + inScale*mFormat->size;
- if (!mFont || h!=mFontHeight || mFont->IsNative()!=inNative || mFont->Rotation()!=inRotation)
+ if (!mFont || h!=mFontHeight )
{
- if (mFont)
- mFont->DecRef();
- mFont = Font::Create(*mFormat,inScale,inRotation,inNative,true);
+ Font *oldFont = mFont;
+ mFont = Font::Create(*mFormat,inScale,inNative,true);
+ if (oldFont)
+ oldFont->DecRef();
mFontHeight = h;
return true;
}
diff --git a/legacy/project/src/common/Tilesheet.cpp b/legacy/project/src/common/Tilesheet.cpp
index af14120f8..0d45f8a7b 100644
--- a/legacy/project/src/common/Tilesheet.cpp
+++ b/legacy/project/src/common/Tilesheet.cpp
@@ -29,7 +29,7 @@ Tilesheet::~Tilesheet()
mSheet->DecRef();
}
-int Tilesheet::AllocRect(int inW,int inH,float inOx, float inOy)
+int Tilesheet::AllocRect(int inW,int inH,float inOx, float inOy,bool inAlphaBorder)
{
Tile tile;
tile.mOx = inOx;
@@ -37,13 +37,19 @@ int Tilesheet::AllocRect(int inW,int inH,float inOx, float inOy)
tile.mSurface = mSheet;
// does it fit on the current row ?
- if (mCurrentX + inW <= mSheet->Width() && mCurrentY + inH < mSheet->Height())
+ int cx = mCurrentX;
+ if (inAlphaBorder && cx>0)
+ cx++;
+ int cy = mCurrentY;
+ if (inAlphaBorder && cy>0)
+ cy++;
+ if (cx + inW <= mSheet->Width() && cy + inH < mSheet->Height())
{
- tile.mRect = Rect(mCurrentX, mCurrentY, inW, inH);
+ tile.mRect = Rect(cx, cy, inW, inH);
int result = mTiles.size();
mTiles.push_back(tile);
- mCurrentX += inW;
- mMaxHeight = std::max(mMaxHeight,inH);
+ mCurrentX = cx+inW;
+ mMaxHeight = std::max(mMaxHeight,inH+cy-mCurrentY);
return result;
}
// No - go to next row
diff --git a/legacy/project/src/common/Utils.cpp b/legacy/project/src/common/Utils.cpp
index 76567e822..f42ed6c2b 100644
--- a/legacy/project/src/common/Utils.cpp
+++ b/legacy/project/src/common/Utils.cpp
@@ -201,14 +201,22 @@ std::string WideToUTF8(const WString &inWideString)
WString IntToWide(int value)
{
wchar_t buffer[16];
+ #ifdef __MINGW32__
+ swprintf(buffer, L"%i", value);
+ #else
swprintf(buffer, 16, L"%i", value);
+ #endif
return WString(buffer);
}
WString ColorToWide(int value)
{
wchar_t buffer[40];
- swprintf(buffer, 40, L"%X", value);
+ #ifdef __MINGW32__
+ swprintf(buffer, L"%X", value);
+ #else
+ swprintf(buffer, 40, L"%i", value);
+ #endif
return WString(buffer);
}
@@ -390,6 +398,15 @@ void GetSpecialDir(SpecialDir inDir,std::string &outDir)
}
else
{
+ #ifdef __MINGW32__
+ #ifndef CSIDL_MYDOCUMENTS
+ #define CSIDL_MYDOCUMENTS CSIDL_PERSONAL
+ #endif
+ #ifndef SHGFP_TYPE_CURRENT
+ #define SHGFP_TYPE_CURRENT 0
+ #endif
+ #endif
+
int id_lut[] = { 0, CSIDL_APPDATA, CSIDL_DESKTOPDIRECTORY, CSIDL_MYDOCUMENTS, CSIDL_PROFILE, 0 };
SHGetFolderPath(NULL, id_lut[inDir], NULL, SHGFP_TYPE_CURRENT, result);
outDir = result;
diff --git a/legacy/project/src/common/XML/tinyxml.h b/legacy/project/src/common/XML/tinyxml.h
index 86475eff7..ca155ddf0 100644
--- a/legacy/project/src/common/XML/tinyxml.h
+++ b/legacy/project/src/common/XML/tinyxml.h
@@ -65,7 +65,11 @@ distribution.
#define TIXML_SAFE
#ifdef TIXML_SAFE
- #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
+ #if defined(__MINGW32__)
+ #define TIXML_SNPRINTF snwprintf
+ //#define TIXML_SNSCANF snscanf
+ #define TIXML_SSCANF swscanf
+ #elif defined(_MSC_VER) && (_MSC_VER >= 1400 ) || defined(__MINGW32__)
// Microsoft visual studio, version 2005 and higher.
#define TIXML_SNPRINTF _snwprintf_s
//#define TIXML_SNSCANF _snwscanf_s
@@ -76,7 +80,7 @@ distribution.
#define TIXML_SNPRINTF _snprintf
//#define TIXML_SNSCANF _snscanf
#define TIXML_SSCANF sscanf
- #elif defined(__GNUC__) && (__GNUC__ >= 3 )
+ #elif (defined(__GNUC__) && (__GNUC__ >= 3 ))
// GCC version 3 and higher.s
//#warning( L"Using sn* functions." )
#define TIXML_SNPRINTF swprintf
diff --git a/legacy/project/src/opengl/OGL.h b/legacy/project/src/opengl/OGL.h
index 26e348e40..4221fa15a 100644
--- a/legacy/project/src/opengl/OGL.h
+++ b/legacy/project/src/opengl/OGL.h
@@ -66,7 +66,11 @@
#include
#include
//#define FORCE_NON_PO2
+#ifdef __MINGW32__
+#include
+#endif
typedef ptrdiff_t GLsizeiptrARB;
+
#define NEED_EXTENSIONS
#include
#include
diff --git a/legacy/project/src/opengl/OGLExport.cpp b/legacy/project/src/opengl/OGLExport.cpp
index 177e6d571..721ffe63c 100644
--- a/legacy/project/src/opengl/OGLExport.cpp
+++ b/legacy/project/src/opengl/OGLExport.cpp
@@ -9,6 +9,7 @@
#ifdef ANDROID
#include
+#include
#endif
#include
@@ -404,6 +405,37 @@ value nme_gl_get_supported_extensions(value ioList)
DEFINE_PRIM(nme_gl_get_supported_extensions,1);
+value nme_gl_get_extension(value inName)
+{
+ void *result = 0;
+ const char *name = val_string(inName);
+
+ #ifdef HX_WINDOWS
+ result = (void *)wglGetProcAddress(name);
+ #elif defined(ANDROID)
+ result = (void *)eglGetProcAddress(name);
+ //Wait until I can test this...
+ //#elif defined(HX_LINUX)
+ // result = dlsym(nme::gOGLLibraryHandle,#func);
+ #endif
+
+ if (result)
+ {
+ static bool init = false;
+ static vkind functionKind;
+ if (!init==0)
+ {
+ init = true;
+ kind_share(&functionKind,"function");
+ }
+ return alloc_abstract(functionKind,result);
+ }
+
+ return alloc_null();
+}
+DEFINE_PRIM(nme_gl_get_extension,1);
+
+
value nme_gl_front_face(value inFace)
{
glFrontFace(val_int(inFace));
diff --git a/legacy/project/src/opengl/OpenGLContext.cpp b/legacy/project/src/opengl/OpenGLContext.cpp
index daf97c49a..b01274a62 100644
--- a/legacy/project/src/opengl/OpenGLContext.cpp
+++ b/legacy/project/src/opengl/OpenGLContext.cpp
@@ -678,7 +678,7 @@ public:
{
// TODO mQuality -> tessellate_lines/tessellate_lines_aa
mLineWidth = inWidth;
- glLineWidth(inWidth);
+ glLineWidth(inWidth<=0.25 ? 0.25 : inWidth);
}
}
diff --git a/legacy/project/src/sdl2/SDL2Stage.cpp b/legacy/project/src/sdl2/SDL2Stage.cpp
index 15cbcca5a..cccc9b013 100644
--- a/legacy/project/src/sdl2/SDL2Stage.cpp
+++ b/legacy/project/src/sdl2/SDL2Stage.cpp
@@ -958,6 +958,7 @@ void AddCharCode(Event &key)
switch (key.value)
{
case 8:
+ case 9:
case 13:
case 27:
case 32:
diff --git a/legacy/project/src/software-renderer/AlphaMask.h b/legacy/project/src/software-renderer/AlphaMask.h
index d701b98bd..5998fcf14 100644
--- a/legacy/project/src/software-renderer/AlphaMask.h
+++ b/legacy/project/src/software-renderer/AlphaMask.h
@@ -112,6 +112,7 @@ public:
virtual void Fill(const AlphaMask &mAlphaMask, int inTX, int inTY, const RenderTarget &inTarget, const RenderState &inState) = 0;
virtual void SetMapping(const UserPoint *inVertex, const float *inUVT, int inComponents) { }
+ virtual void SetTint(ARGB inTint) { }
static Filler *Create(GraphicsSolidFill *inFill);
static Filler *Create(GraphicsGradientFill *inFill);
diff --git a/legacy/project/src/software-renderer/BitmapFill.cpp b/legacy/project/src/software-renderer/BitmapFill.cpp
index 5cd69fdfd..13e4d13d1 100644
--- a/legacy/project/src/software-renderer/BitmapFill.cpp
+++ b/legacy/project/src/software-renderer/BitmapFill.cpp
@@ -7,10 +7,12 @@ namespace nme
template
static Filler *CreateAlpha(GraphicsBitmapFill *inFill)
{
- if (inFill->bitmapData->Format() & pfHasAlpha)
- return new BitmapFiller(inFill);
+ if (inFill->bitmapData->Format() == pfAlpha)
+ return new BitmapFiller(inFill);
+ else if (inFill->bitmapData->Format() & pfHasAlpha)
+ return new BitmapFiller(inFill);
else
- return new BitmapFiller(inFill);
+ return new BitmapFiller(inFill);
}
diff --git a/legacy/project/src/software-renderer/BitmapFill.h b/legacy/project/src/software-renderer/BitmapFill.h
index 3364d9688..1ac1f7914 100644
--- a/legacy/project/src/software-renderer/BitmapFill.h
+++ b/legacy/project/src/software-renderer/BitmapFill.h
@@ -12,81 +12,12 @@ static inline bool IsPOW2(int inX)
enum { EDGE_CLAMP, EDGE_REPEAT, EDGE_POW2 };
-
-#define GET_PIXEL_POINTERS \
- int frac_x = (mPos.x & 0xff00) >> 8; \
- int frac_y = (mPos.y & 0xff00) >> 8; \
- \
- if (EDGE == EDGE_CLAMP) \
- { \
- int x_step = 4; \
- int y_step = mStride; \
- \
- if (x<0) { x_step = x = 0; } \
- else if (x>=mW1) { x_step = 0; x = mW1; } \
- \
- if (y<0) { y_step = y = 0; } \
- else if (y>=mH1) { y_step = 0; y = mH1; } \
- \
- const uint8 * ptr = mBase + y*mStride + x*4; \
- p00 = *(ARGB *)ptr; \
- p01 = *(ARGB *)(ptr + x_step); \
- p10 = *(ARGB *)(ptr + y_step); \
- p11 = *(ARGB *)(ptr + y_step + x_step); \
- } \
- else if (EDGE==EDGE_POW2) \
- { \
- const uint8 *p = mBase + (y&mH1)*mStride; \
- \
- p00 = *(ARGB *)(p+ (x & mW1)*4); \
- p01 = *(ARGB *)(p+ ((x+1) & mW1)*4); \
- \
- p = mBase + ( (y+1) &mH1)*mStride; \
- p10 = *(ARGB *)(p+ (x & mW1)*4); \
- p11 = *(ARGB *)(p+ ((x+1) & mW1)*4); \
- } \
- else \
- { \
- int x1 = ((x+1) % mWidth) * 4; \
- if (x1<0) x1+=mWidth; \
- x = (x % mWidth)*4; \
- if (x<0) x+=mWidth; \
- \
- int y0= (y%mHeight); if (y0<0) y0+=mHeight; \
- const uint8 *p = mBase + y0*mStride; \
- \
- p00 = *(ARGB *)(p+ x); \
- p01 = *(ARGB *)(p+ x1); \
-\
- int y1= ((y+1)%mHeight); if (y1<0) y1+=mHeight; \
- p = mBase + y1*mStride; \
- p10 = *(ARGB *)(p+ x); \
- p11 = *(ARGB *)(p+ x1); \
- }
-
-
-
-#define MODIFY_EDGE_XY \
- if (EDGE == EDGE_CLAMP) \
- { \
- if (x<0) x = 0; \
- else if (x>=mWidth) x = mW1; \
- \
- if (y<0) y = 0; \
- else if (y>=mHeight) y = mH1; \
- } \
- else if (EDGE == EDGE_POW2) \
- { \
- x &= mW1; \
- y &= mH1; \
- } \
- else if (EDGE == EDGE_REPEAT) \
- { \
- x = x % mWidth; if (x<0) x+=mWidth;\
- y = y % mHeight; if (y<0) y+=mHeight;\
- }
-
-
+enum FillAlphaMode
+{
+ FillAlphaIgnore,
+ FillAlphaHas,
+ FillAlphaIs,
+};
@@ -104,6 +35,7 @@ public:
mMapped = false;
mPerspective = false;
mBilinearAdjust = 0;
+ mTint = ARGB(0xffffffff);
}
@@ -121,6 +53,9 @@ public:
mDPyDX = (int)(mMapper.m10 * (1<<16)+ 0.5);
}
+ void SetTint(ARGB inTint) { mTint = inTint; }
+
+
void SetMapping(const UserPoint *inVertex, const float *inUVT,int inComponents)
{
mMapped = true;
@@ -246,15 +181,17 @@ public:
double mTX, mTY, mTW;
double mBilinearAdjust;
Matrix mMapper;
+ ARGB mTint;
GraphicsBitmapFill *mBitmap;
};
-template
+template
class BitmapFiller : public BitmapFillerBase
{
public:
- enum { HasAlpha = HAS_ALPHA };
+ enum { HasAlpha = FILL_ALPHA!=FillAlphaIgnore };
+ enum { AlphaMode = FILL_ALPHA };
BitmapFiller(GraphicsBitmapFill *inFill) : BitmapFillerBase(inFill)
{
@@ -273,43 +210,154 @@ public:
mTY += mMapper.m10;
mTW += mWX;
}
+
int x = mPos.x >> 16;
int y = mPos.y >> 16;
if (SMOOTH)
{
ARGB result;
- ARGB p00,p01,p10,p11;
-
- GET_PIXEL_POINTERS
+ int frac_x = (mPos.x & 0xff00) >> 8;
+ int frac_y = (mPos.y & 0xff00) >> 8;
if (!PERSP)
{
mPos.x += mDPxDX;
mPos.y += mDPyDX;
}
-
- int y0r = (p00.r<<8) + (p01.r-p00.r) * frac_x;
- int y1r = (p10.r<<8) + (p11.r-p10.r) * frac_x;
- result.r = ((y0r<<8) + (y1r-y0r) * frac_y)>>16;
- int y0g = (p00.g<<8) + (p01.g-p00.g) * frac_x;
- int y1g = (p10.g<<8) + (p11.g-p10.g) * frac_x;
- result.g = ((y0g<<8) + (y1g-y0g) * frac_y)>>16;
-
- int y0b = (p00.b<<8) + (p01.b-p00.b) * frac_x;
- int y1b = (p10.b<<8) + (p11.b-p10.b) * frac_x;
- result.b = ((y0b<<8) + (y1b-y0b) * frac_y)>>16;
-
- if (HAS_ALPHA)
+ if ((FillAlphaMode)AlphaMode==FillAlphaIs)
{
- int y0a = (p00.a<<8) + (p01.a-p00.a) * frac_x;
- int y1a = (p10.a<<8) + (p11.a-p10.a) * frac_x;
+ int a00,a01,a10,a11;
+
+ if (EDGE == EDGE_CLAMP)
+ {
+ int x_step = 1;
+ int y_step = mStride;
+
+ if (x<0) { x_step = x = 0; }
+ else if (x>=mW1) { x_step = 0; x = mW1; }
+
+ if (y<0) { y_step = y = 0; }
+ else if (y>=mH1) { y_step = 0; y = mH1; }
+
+ const uint8 * ptr = mBase + y*mStride + x;
+ a00 = ptr[0];
+ a01 = ptr[x_step];
+ a10 = ptr[y_step];
+ a11 = ptr[y_step + x_step];
+ }
+ else if (EDGE==EDGE_POW2)
+ {
+ const uint8 *p = mBase + (y&mH1)*mStride;
+
+ a00 = *(p+ (x & mW1));
+ a01 = *(p+ ((x+1) & mW1));
+
+ p = mBase + ( (y+1) &mH1)*mStride;
+ a10 = *(p+ (x & mW1));
+ a11 = *(p+ ((x+1) & mW1));
+ }
+ else
+ {
+ int x1 = ((x+1) % mWidth);
+ if (x1<0) x1+=mWidth;
+ x = (x % mWidth);
+ if (x<0) x+=mWidth;
+
+ int y0= (y%mHeight); if (y0<0) y0+=mHeight;
+ const uint8 *p = mBase + y0*mStride;
+
+ a00 = *(p+ x);
+ a01 = *(p+ x1);
+
+ int y1= ((y+1)%mHeight); if (y1<0) y1+=mHeight;
+ p = mBase + y1*mStride;
+ a10 = *(p+ x);
+ a11 = *(p+ x1);
+ }
+
+ int y0a = (a00<<8) + (a01-a00) * frac_x;
+ int y1a = (a10<<8) + (a11-a10) * frac_x;
+ result = mTint;
result.a = ((y0a<<8) + (y1a-y0a) * frac_y)>>16;
+
+ return result;
}
else
{
- result.a = 255;
+ ARGB p00,p01,p10,p11;
+
+ if (EDGE == EDGE_CLAMP)
+ {
+ int x_step = 4;
+ int y_step = mStride;
+
+ if (x<0) { x_step = x = 0; }
+ else if (x>=mW1) { x_step = 0; x = mW1; }
+
+ if (y<0) { y_step = y = 0; }
+ else if (y>=mH1) { y_step = 0; y = mH1; }
+
+ const uint8 * ptr = mBase + y*mStride + x*4;
+ p00 = *(ARGB *)ptr;
+ p01 = *(ARGB *)(ptr + x_step);
+ p10 = *(ARGB *)(ptr + y_step);
+ p11 = *(ARGB *)(ptr + y_step + x_step);
+ }
+ else if (EDGE==EDGE_POW2)
+ {
+ const uint8 *p = mBase + (y&mH1)*mStride;
+
+ p00 = *(ARGB *)(p+ (x & mW1)*4);
+ p01 = *(ARGB *)(p+ ((x+1) & mW1)*4);
+
+ p = mBase + ( (y+1) &mH1)*mStride;
+ p10 = *(ARGB *)(p+ (x & mW1)*4);
+ p11 = *(ARGB *)(p+ ((x+1) & mW1)*4);
+ }
+ else
+ {
+ int x1 = ((x+1) % mWidth) * 4;
+ if (x1<0) x1+=mWidth;
+ x = (x % mWidth)*4;
+ if (x<0) x+=mWidth;
+
+ int y0= (y%mHeight); if (y0<0) y0+=mHeight;
+ const uint8 *p = mBase + y0*mStride;
+
+ p00 = *(ARGB *)(p+ x);
+ p01 = *(ARGB *)(p+ x1);
+
+ int y1= ((y+1)%mHeight); if (y1<0) y1+=mHeight;
+ p = mBase + y1*mStride;
+ p10 = *(ARGB *)(p+ x);
+ p11 = *(ARGB *)(p+ x1);
+ }
+
+
+ int y0r = (p00.r<<8) + (p01.r-p00.r) * frac_x;
+ int y1r = (p10.r<<8) + (p11.r-p10.r) * frac_x;
+ result.r = ((y0r<<8) + (y1r-y0r) * frac_y)>>16;
+
+ int y0g = (p00.g<<8) + (p01.g-p00.g) * frac_x;
+ int y1g = (p10.g<<8) + (p11.g-p10.g) * frac_x;
+ result.g = ((y0g<<8) + (y1g-y0g) * frac_y)>>16;
+
+ int y0b = (p00.b<<8) + (p01.b-p00.b) * frac_x;
+ int y1b = (p10.b<<8) + (p11.b-p10.b) * frac_x;
+ result.b = ((y0b<<8) + (y1b-y0b) * frac_y)>>16;
+
+ if ((FillAlphaMode)AlphaMode==FillAlphaHas)
+ {
+ int y0a = (p00.a<<8) + (p01.a-p00.a) * frac_x;
+ int y1a = (p10.a<<8) + (p11.a-p10.a) * frac_x;
+ result.a = ((y0a<<8) + (y1a-y0a) * frac_y)>>16;
+ }
+ else
+ {
+ result.a = 255;
+ }
}
return result;
@@ -321,8 +369,36 @@ public:
mPos.x += mDPxDX;
mPos.y += mDPyDX;
}
- MODIFY_EDGE_XY;
- return *(ARGB *)( mBase + y*mStride + x*4);
+
+ if (EDGE == EDGE_CLAMP)
+ {
+ if (x<0) x = 0;
+ else if (x>=mWidth) x = mW1;
+
+ if (y<0) y = 0;
+ else if (y>=mHeight) y = mH1;
+ }
+ else if (EDGE == EDGE_POW2)
+ {
+ x &= mW1;
+ y &= mH1;
+ }
+ else if (EDGE == EDGE_REPEAT)
+ {
+ x = x % mWidth; if (x<0) x+=mWidth;
+ y = y % mHeight; if (y<0) y+=mHeight;
+ }
+
+ if ((FillAlphaMode)AlphaMode==FillAlphaIs)
+ {
+ ARGB result(mTint);
+ result.a = *( mBase + y*mStride + x);
+ return result;
+ }
+ else
+ {
+ return *(ARGB *)( mBase + y*mStride + x*4);
+ }
}
}
diff --git a/legacy/project/src/software-renderer/BitmapFillPerspective.cpp b/legacy/project/src/software-renderer/BitmapFillPerspective.cpp
index 0b7291adc..829c90af4 100644
--- a/legacy/project/src/software-renderer/BitmapFillPerspective.cpp
+++ b/legacy/project/src/software-renderer/BitmapFillPerspective.cpp
@@ -7,10 +7,12 @@ namespace nme
template
static Filler *CreateAlpha(GraphicsBitmapFill *inFill)
{
- if (inFill->bitmapData->Format() & pfHasAlpha)
- return new BitmapFiller(inFill);
+ if (inFill->bitmapData->Format() == pfAlpha)
+ return new BitmapFiller(inFill);
+ else if (inFill->bitmapData->Format() & pfHasAlpha)
+ return new BitmapFiller(inFill);
else
- return new BitmapFiller(inFill);
+ return new BitmapFiller(inFill);
}
diff --git a/legacy/project/src/software-renderer/TileRenderer.cpp b/legacy/project/src/software-renderer/TileRenderer.cpp
index 00d8e7d0d..4d65bc943 100644
--- a/legacy/project/src/software-renderer/TileRenderer.cpp
+++ b/legacy/project/src/software-renderer/TileRenderer.cpp
@@ -35,9 +35,9 @@ struct TileData
{
UserPoint rg = inPoint[0];
UserPoint ba = inPoint[1];
- mColour = ((rg.x<0 ? 0 : rg.x>1?255 : (int)(rg.x*255))) |
+ mColour = ((rg.x<0 ? 0 : rg.x>1?255 : (int)(rg.x*255))<<16) |
((rg.y<0 ? 0 : rg.y>1?255 : (int)(rg.y*255))<<8) |
- ((ba.x<0 ? 0 : ba.x>1?255 : (int)(ba.x*255))<<16) |
+ ((ba.x<0 ? 0 : ba.x>1?255 : (int)(ba.x*255))) |
((ba.y<0 ? 0 : ba.y>1?255 : (int)(ba.y*255))<<24);
}
}
@@ -164,7 +164,12 @@ public:
UserPoint corner(data.mPos);
UserPoint pos = inState.mTransform.mMatrix->Apply(corner.x,corner.y);
- if ( (is_stretch || data.mHasTrans) )
+ if (s->Format()==pfAlpha && !is_stretch && mBlendMode==bmNormal && data.mHasColour /* integer co-ordinate?*/ )
+ {
+ unsigned int col = inState.mColourTransform->Transform(data.mColour|0xff000000);
+ s->BlitTo(inTarget, data.mRect, (int)(pos.x), (int)(pos.y), blend, 0, col);
+ }
+ else if ( (is_stretch || data.mHasTrans) )
{
// Can use stretch if there is no skew and no colour transform...
if (!data.mHasColour && (!data.mHasTrans) && mBlendMode==bmNormal )
@@ -236,8 +241,8 @@ public:
SpanRect *span = new SpanRect(alpha_rect,aa);
for(int i=0;i<4;i++)
span->Line00(
- Fixed10( p[i].x + 0.5 , p[i].y + 0.5 ),
- Fixed10( p[(i+1)&3].x + 0.5 , p[(i+1)&3].y + 0.5 ) );
+ Fixed10( p[i].x, p[i].y ),
+ Fixed10( p[(i+1)&3].x, p[(i+1)&3].y) );
AlphaMask *alpha = span->CreateMask(inState.mTransform,tile_alpha);
delete span;
@@ -250,11 +255,20 @@ public:
uvt[4] = (data.mRect.x + data.mRect.w) * bmp_scale_x;
uvt[5] = (data.mRect.y + data.mRect.h) * bmp_scale_y;
mFiller->SetMapping(p,uvt,2);
-
+
// Can render straight to surface ....
if (!offscreen_buffer)
{
- if (data.mHasTrans && !just_alpha)
+ if (s->Format()==pfAlpha)
+ {
+ if (data.mHasColour)
+ {
+ ARGB col = inState.mColourTransform->Transform(data.mColour|0xff000000);
+ mFiller->SetTint(col);
+ }
+ mFiller->Fill(*alpha,0,0,inTarget,inState);
+ }
+ else if (data.mHasTrans && !just_alpha)
{
ColorTransform buf;
RenderState col_state(inState);
@@ -277,6 +291,14 @@ public:
{
AutoSurfaceRender tmp_render(tmp);
const RenderTarget &target = tmp_render.Target();
+
+ if (s->Format()==pfAlpha && data.mHasColour)
+ {
+ ARGB col = inState.mColourTransform->Transform(data.mColour|0xff000000);
+ mFiller->SetTint(col);
+ }
+
+
mFiller->Fill(*alpha,0,0,target,inState);
}
diff --git a/legacy/project/src/windows/CaptureDevice.cpp b/legacy/project/src/windows/CaptureDevice.cpp
index aad747342..a866da2f8 100644
--- a/legacy/project/src/windows/CaptureDevice.cpp
+++ b/legacy/project/src/windows/CaptureDevice.cpp
@@ -1,3 +1,5 @@
+#ifndef __MINGW32__
+
#include
#include
#include
@@ -491,3 +493,18 @@ Camera *CreateCamera(const char *inName)
} // end namespace name
+#else // __MINGW__
+
+
+#include
+namespace nme
+{
+
+Camera *CreateCamera(const char *inName)
+{
+ return 0;
+}
+
+} // end namespace name
+
+#endif
diff --git a/legacy/project/src/windows/GDIFont.cpp b/legacy/project/src/windows/GDIFont.cpp
index 979f7652c..59e0f00e6 100644
--- a/legacy/project/src/windows/GDIFont.cpp
+++ b/legacy/project/src/windows/GDIFont.cpp
@@ -101,7 +101,6 @@ public:
ioMetrics.ascent = std::max( ioMetrics.ascent, (float)mMetrics.tmAscent);
ioMetrics.descent = std::max( ioMetrics.descent, (float)mMetrics.tmDescent);
ioMetrics.height = std::max( ioMetrics.height, (float)mMetrics.tmHeight);
- //ioMetrics.height = std::max( ioMetrics.height, (float)mPixelHeight);
}
int Height()
diff --git a/legacy/project/src/windows/System.cpp b/legacy/project/src/windows/System.cpp
index c9ac16058..de1564f75 100644
--- a/legacy/project/src/windows/System.cpp
+++ b/legacy/project/src/windows/System.cpp
@@ -17,6 +17,13 @@ namespace nme {
std::string CapabilitiesGetLanguage()
{
char locale[8];
+ #ifdef __MINGW32__
+ typedef WINBASEAPI LANGID WINAPI (*GetSystemDefaultUILanguageFunc)();
+ GetSystemDefaultUILanguageFunc GetSystemDefaultUILanguage =
+ (GetSystemDefaultUILanguageFunc)GetProcAddress( LoadLibraryA("kernel32.dll"), "GetSystemDefaultUILanguage");
+ if (!GetSystemDefaultUILanguage)
+ return "en";
+ #endif
int lang_len = GetLocaleInfo(GetSystemDefaultUILanguage(), LOCALE_SISO639LANGNAME, locale, sizeof(locale));
return std::string(locale, lang_len);
}