diff --git a/src/Sexy.TodLib/TodCommon.cpp b/src/Sexy.TodLib/TodCommon.cpp index f1a9d6f..b876d62 100644 --- a/src/Sexy.TodLib/TodCommon.cpp +++ b/src/Sexy.TodLib/TodCommon.cpp @@ -13,6 +13,7 @@ #include "../SexyAppFramework/PerfTimer.h" #include "../SexyAppFramework/SexyMatrix.h" #include "../SexyAppFramework/Renderer.h" +#include "../SexyAppFramework/RenderCommand.h" void Tod_SWTri_AddAllDrawTriFuncs() { @@ -199,7 +200,7 @@ uintptr_t TodPickFromSmoothArray(TodSmoothArray *theArray, int theCount) for (int j = 0; j < theCount; j++) { aTotalAdjustedWeight += TodCalcSmoothWeight(theArray[j].mWeight * aNormalizeFactor, theArray[j].mLastPicked, - theArray[j].mSecondLastPicked); + theArray[j].mSecondLastPicked); } TOD_ASSERT(aTotalAdjustedWeight > 0.0f); @@ -209,7 +210,7 @@ uintptr_t TodPickFromSmoothArray(TodSmoothArray *theArray, int theCount) for (k = 0; k < theCount - 1; k++) { aAccumulatedWeight += TodCalcSmoothWeight(theArray[k].mWeight * aNormalizeFactor, theArray[k].mLastPicked, - theArray[k].mSecondLastPicked); + theArray[k].mSecondLastPicked); if (aRandWeight <= aAccumulatedWeight) { break; @@ -392,8 +393,8 @@ float TodCurveEvaluateClamped(float theTime, float thePositionStart, float thePo if (theTime >= 1.0f) { if (theCurve == TodCurves::CURVE_BOUNCE || theCurve == TodCurves::CURVE_BOUNCE_FAST_MIDDLE || - theCurve == TodCurves::CURVE_BOUNCE_SLOW_MIDDLE || theCurve == TodCurves::CURVE_SIN_WAVE || - theCurve == TodCurves::CURVE_EASE_SIN_WAVE) + theCurve == TodCurves::CURVE_BOUNCE_SLOW_MIDDLE || theCurve == TodCurves::CURVE_SIN_WAVE || + theCurve == TodCurves::CURVE_EASE_SIN_WAVE) { return thePositionStart; } @@ -407,14 +408,14 @@ float TodCurveEvaluateClamped(float theTime, float thePositionStart, float thePo } float TodAnimateCurveFloatTime(float theTimeStart, float theTimeEnd, float theTimeAge, float thePositionStart, - float thePositionEnd, TodCurves theCurve) + float thePositionEnd, TodCurves theCurve) { float aWarpedAge = (theTimeAge - theTimeStart) / (theTimeEnd - theTimeStart); return TodCurveEvaluateClamped(aWarpedAge, thePositionStart, thePositionEnd, theCurve); } float TodAnimateCurveFloat(int theTimeStart, int theTimeEnd, int theTimeAge, float thePositionStart, - float thePositionEnd, TodCurves theCurve) + float thePositionEnd, TodCurves theCurve) { //return TodAnimateCurveFloatTime(theTimeStart, theTimeEnd, theTimeAge, thePositionStart, thePositionEnd, theCurve); @@ -423,10 +424,10 @@ float TodAnimateCurveFloat(int theTimeStart, int theTimeEnd, int theTimeAge, flo } int TodAnimateCurve(int theTimeStart, int theTimeEnd, int theTimeAge, int thePositionStart, int thePositionEnd, - TodCurves theCurve) + TodCurves theCurve) { return FloatRoundToInt( - TodAnimateCurveFloat(theTimeStart, theTimeEnd, theTimeAge, thePositionStart, thePositionEnd, theCurve)); + TodAnimateCurveFloat(theTimeStart, theTimeEnd, theTimeAge, thePositionStart, thePositionEnd, theCurve)); } int RandRangeInt(int theMin, int theMax) @@ -442,18 +443,18 @@ float RandRangeFloat(float theMin, float theMax) } void TodDrawString(Graphics *g, const SexyString &theText, int thePosX, int thePosY, Font *theFont, - const Color &theColor, DrawStringJustification theJustification) + const Color &theColor, DrawStringJustification theJustification) { SexyString aFinalString = TodStringTranslate(theText); int aPosX = thePosX; if (theJustification == DrawStringJustification::DS_ALIGN_RIGHT || - theJustification == DrawStringJustification::DS_ALIGN_RIGHT_VERTICAL_MIDDLE) + theJustification == DrawStringJustification::DS_ALIGN_RIGHT_VERTICAL_MIDDLE) { aPosX -= theFont->StringWidth(aFinalString); } else if (theJustification == DrawStringJustification::DS_ALIGN_CENTER || - theJustification == DrawStringJustification::DS_ALIGN_CENTER_VERTICAL_MIDDLE) + theJustification == DrawStringJustification::DS_ALIGN_CENTER_VERTICAL_MIDDLE) { aPosX -= theFont->StringWidth(aFinalString) / 2; } @@ -462,7 +463,7 @@ void TodDrawString(Graphics *g, const SexyString &theText, int thePosX, int theP } void TodDrawImageCelScaled(Graphics *g, Image *theImageStrip, int thePosX, int thePosY, int theCelCol, int theCelRow, - float theScaleX, float theScaleY) + float theScaleX, float theScaleY) { TOD_ASSERT(theCelCol >= 0 && theCelCol < theImageStrip->mNumCols); TOD_ASSERT(theCelRow >= 0 && theCelRow < theImageStrip->mNumRows); @@ -474,28 +475,22 @@ void TodDrawImageCelScaled(Graphics *g, Image *theImageStrip, int thePosX, int t g->DrawImage(theImageStrip, aDestRect, aSrcRect); } -static const int POOL_SIZE = 4096; -static RenderCommand gRenderCommandPool[POOL_SIZE]; -static RenderCommand *gRenderTail[256]; -static RenderCommand *gRenderHead[256]; - -void TodDrawStringMatrix(Graphics *g, const Font *theFont, const SexyMatrix3 &theMatrix, const SexyString &theString, - const Color &theColor) +static RenderCommandList gDrawStringMatrixRenderCommandList; +void TodDrawStringMatrix(Graphics *g, Font *theFont, + const SexyMatrix3 &theMatrix, const SexyString &theString, + const Color &theColor) { SexyString aFinalString = TodStringTranslate(theString); + gDrawStringMatrixRenderCommandList.Clear(); - memset(gRenderTail, 0, sizeof(gRenderTail)); - memset(gRenderHead, 0, sizeof(gRenderHead)); ImageFont *aFont = (ImageFont *)theFont; if (!aFont->mFontData->mInitialized) return; aFont->Prepare(); int aCurXPos = 0; - int aCurPoolIdx = 0; auto it = theString.begin(); auto end = theString.end(); - while (it != end) { uint32_t aCodepoint = utf8::next(it, end); @@ -565,40 +560,18 @@ void TodDrawStringMatrix(Graphics *g, const Font *theFont, const SexyMatrix3 &th aColor.mAlpha = std::min(aLayer->mColorAdd.mAlpha + theColor.mAlpha * aLayer->mColorMult.mAlpha / 255, 255); int anOrder = aCharData->mOrder + aLayer->mBaseOrder; - if (aCurPoolIdx >= POOL_SIZE) + RenderCommand *aRenderCommand = gDrawStringMatrixRenderCommandList.PushWithOrder(anOrder); + if (!aRenderCommand) + { break; - - RenderCommand *aRenderCommand = &gRenderCommandPool[aCurPoolIdx++]; + } aRenderCommand->mImage = aKernItr->mScaledImage; aRenderCommand->mColor = aColor; - aRenderCommand->mDest[0] = anImageX; - aRenderCommand->mDest[1] = anImageY; - aRenderCommand->mSrc[0] = aKernItr->mScaledCharImageRects[aChar].mX; - aRenderCommand->mSrc[1] = aKernItr->mScaledCharImageRects[aChar].mY; - aRenderCommand->mSrc[2] = aKernItr->mScaledCharImageRects[aChar].mWidth; - aRenderCommand->mSrc[3] = aKernItr->mScaledCharImageRects[aChar].mHeight; - + aRenderCommand->mDestX = anImageX; + aRenderCommand->mDestY = anImageY; + aRenderCommand->mSrc = aKernItr->mScaledCharImageRects[aChar]; aRenderCommand->mMode = aLayer->mDrawMode; - //aRenderCommand->mUseAlphaCorrection = aLayer->mUseAlphaCorrection; - aRenderCommand->mNext = nullptr; - int anOrderIdx = std::min(std::max(anOrder + 128, 0), 255); - if (gRenderTail[anOrderIdx]) - { - gRenderTail[anOrderIdx]->mNext = aRenderCommand; - gRenderTail[anOrderIdx] = aRenderCommand; - } - else - { - gRenderHead[anOrderIdx] = aRenderCommand; - gRenderTail[anOrderIdx] = aRenderCommand; - } - - //aCurXPos += aSpacing + aCharWidth; - //if (aCurXPos > aMaxXPos) - //{ - // aMaxXPos = aCurXPos; - //} if (aMaxXPos < aCurXPos + aSpacing + aCharWidth) { aMaxXPos = aCurXPos + aSpacing + aCharWidth; @@ -608,32 +581,19 @@ void TodDrawStringMatrix(Graphics *g, const Font *theFont, const SexyMatrix3 &th aCurXPos = aMaxXPos; } - for (int aPoolIdx = 0; aPoolIdx < 256; aPoolIdx++) + for (const auto &command : gDrawStringMatrixRenderCommandList) { - RenderCommand *aRenderCommand = gRenderHead[aPoolIdx]; - - while (aRenderCommand) + int aDrawMode = command.mMode == -1 ? g->GetDrawMode() : command.mMode; + if (command.mImage) { - int aDrawMode = g->GetDrawMode(); - if (aRenderCommand->mMode != -1) - { - aDrawMode = aRenderCommand->mMode; - } - - if (aRenderCommand->mImage) - { - Rect aSrcRect(aRenderCommand->mSrc[0], aRenderCommand->mSrc[1], aRenderCommand->mSrc[2], - aRenderCommand->mSrc[3]); - SexyTransform2D aTransform; - float aPosX = aSrcRect.mWidth * 0.5f + aRenderCommand->mDest[0]; - float aPosY = aSrcRect.mHeight * 0.5f + aRenderCommand->mDest[1]; - SexyMatrix3Translation(aTransform, aPosX, aPosY); - SexyMatrix3Multiply(aTransform, theMatrix, aTransform); - TodBltMatrix(g, aRenderCommand->mImage, aTransform, g->mClipRect, aRenderCommand->mColor, aDrawMode, - aSrcRect); - } - - aRenderCommand = aRenderCommand->mNext; + const Rect &aSrcRect = command.mSrc; + SexyTransform2D aTransform; + float aPosX = aSrcRect.mWidth * 0.5f + command.mDestX; + float aPosY = aSrcRect.mHeight * 0.5f + command.mDestY; + SexyMatrix3Translation(aTransform, aPosX, aPosY); + SexyMatrix3Multiply(aTransform, theMatrix, aTransform); + TodBltMatrix(g, command.mImage, aTransform, g->mClipRect, command.mColor, aDrawMode, + aSrcRect); } } } @@ -721,7 +681,7 @@ void TodSandImageIfNeeded(Image *theImage) } void TodBltMatrix(Graphics *g, Image *theImage, const SexyMatrix3 &theTransform, const Rect &theClipRect, - const Color &theColor, int theDrawMode, const Rect &theSrcRect) + const Color &theColor, int theDrawMode, const Rect &theSrcRect) { float aOffsetX = 0.0f; float aOffsetY = 0.0f; @@ -733,30 +693,30 @@ void TodBltMatrix(Graphics *g, Image *theImage, const SexyMatrix3 &theTransform, TodSandImageIfNeeded(theImage); if (theClipRect.mX != 0 || theClipRect.mY != 0 || theClipRect.mWidth != BOARD_WIDTH || - theClipRect.mHeight != BOARD_HEIGHT) + theClipRect.mHeight != BOARD_HEIGHT) { g->mDestImage->BltMatrix(theImage, aOffsetX, aOffsetY, theTransform, theClipRect, theColor, theDrawMode, - theSrcRect, g->mLinearBlend); + theSrcRect, g->mLinearBlend); } else if (GPUImage::Check3D(g->mDestImage)) { theImage->mDrawn = true; Renderer *aInterface = ((GPUImage *)g->mDestImage)->mRenderer; aInterface->BltTransformed(theImage, theClipRect, theColor, theDrawMode, theSrcRect, theTransform, - g->mLinearBlend, aOffsetX, aOffsetY, true); + g->mLinearBlend, aOffsetX, aOffsetY, true); } else { Rect aBufFixClipRect(0, 0, BOARD_WIDTH + 1, BOARD_HEIGHT + 1); g->mDestImage->BltMatrix(theImage, aOffsetX, aOffsetY, theTransform, aBufFixClipRect, theColor, theDrawMode, - theSrcRect, g->mLinearBlend); + theSrcRect, g->mLinearBlend); } gTodTriangleDrawAdditive = false; } void TodDrawImageCelCenterScaledF(Graphics *g, Image *theImageStrip, float thePosX, float thePosY, int theCelCol, - int theCelRow, float theScaleX, float theScaleY) + int theCelRow, float theScaleX, float theScaleY) { TOD_ASSERT(theCelCol >= 0 && theCelCol < theImageStrip->mNumCols); TOD_ASSERT(theCelRow >= 0 && theCelRow < theImageStrip->mNumRows); @@ -789,7 +749,7 @@ void TodDrawImageCelCenterScaledF(Graphics *g, Image *theImageStrip, float thePo } void TodDrawImageCelScaledF(Graphics *g, Image *theImageStrip, float thePosX, float thePosY, int theCelCol, - int theCelRow, float theScaleX, float theScaleY) + int theCelRow, float theScaleX, float theScaleY) { TOD_ASSERT(theCelCol >= 0 && theCelCol < theImageStrip->mNumCols); TOD_ASSERT(theCelRow >= 0 && theCelRow < theImageStrip->mNumRows); @@ -849,7 +809,7 @@ void TodDrawImageScaledF(Graphics *g, Image *theImage, float thePosX, float theP } void TodDrawImageCenterScaledF(Graphics *g, Image *theImage, float thePosX, float thePosY, float theScaleX, - float theScaleY) + float theScaleY) { if (theScaleX == 1.0f && theScaleY == 1.0f) { @@ -893,7 +853,7 @@ uint32_t AverageNearByPixels(MemoryImage *theImage, uint32_t *thePixel, int x, i for (int j = -1; j <= 1; j++) { if ((x != 0 || j != -1) && (x != theImage->mWidth - 1 || j != 1) && (y != 0 || i != -1) && - (y != theImage->mHeight - 1 || i != 1)) + (y != theImage->mHeight - 1 || i != 1)) { unsigned long aPixel = *(thePixel + i * theImage->mWidth + j); if (aPixel & 0xFF000000UL) @@ -951,7 +911,7 @@ void FixPixelsOnAlphaEdgeForBlending(Image *theImage) if (aDuration > 20) { TodTraceAndLog("[TodLib] - LOADING:Long sanding '%s' %d ms on %s", theImage->mFilePath.c_str(), aDuration, - gGetCurrentLevelName().c_str()); + gGetCurrentLevelName().c_str()); } } @@ -980,7 +940,7 @@ void SexyMatrix3Transpose(const SexyMatrix3 &m, SexyMatrix3 &r) void SexyMatrix3Inverse(const SexyMatrix3 &m, SexyMatrix3 &r) { float aDet = (m.m22 * m.m11 - m.m21 * m.m12) * m.m00 - (m.m22 * m.m10 - m.m20 * m.m12) * m.m01 + - (m.m21 * m.m10 - m.m20 * m.m11) * m.m02; + (m.m21 * m.m10 - m.m20 * m.m11) * m.m02; float aInvDet = 1.0f / aDet; SexyMatrix3 temp; @@ -1053,9 +1013,9 @@ int ColorComponentMultiply(int theColor1, int theColor2) Color ColorsMultiply(const Color &theColor1, const Color &theColor2) { return Color(ColorComponentMultiply(theColor1.mRed, theColor2.mRed), - ColorComponentMultiply(theColor1.mGreen, theColor2.mGreen), - ColorComponentMultiply(theColor1.mBlue, theColor2.mBlue), - ColorComponentMultiply(theColor1.mAlpha, theColor2.mAlpha)); + ColorComponentMultiply(theColor1.mGreen, theColor2.mGreen), + ColorComponentMultiply(theColor1.mBlue, theColor2.mBlue), + ColorComponentMultiply(theColor1.mAlpha, theColor2.mAlpha)); } bool TodLoadResources(const std::string &theGroup) @@ -1095,7 +1055,7 @@ bool TodResourceManager::TodLoadResources(const std::string &theGroup) if (aDuration > 20) { TodTraceAndLog("[TodLib] - LOADED: '%s' %d ms on %s", theGroup.c_str(), aDuration, - gGetCurrentLevelName().c_str()); + gGetCurrentLevelName().c_str()); } return true; @@ -1261,7 +1221,7 @@ void FreeGlobalAllocators() } SexyString TodReplaceString(const SexyString &theText, const SexyString &theStringToFind, - const SexyString &theStringToSubstitute) + const SexyString &theStringToSubstitute) { SexyString aFinalString = TodStringTranslate(theText); size_t aPos = aFinalString.find(theStringToFind); @@ -1288,7 +1248,7 @@ SexyString TodReplaceNumberString(const SexyString &theText, const SexyString &t } bool TodIsPointInPolygon(const SexyVector2 *thePolygonPoint, int theNumberPolygonPoints, - const SexyVector2 &theCheckPoint) + const SexyVector2 &theCheckPoint) { TOD_ASSERT(theNumberPolygonPoints >= 3); diff --git a/src/Sexy.TodLib/TodCommon.h b/src/Sexy.TodLib/TodCommon.h index 328c0a5..67599d6 100644 --- a/src/Sexy.TodLib/TodCommon.h +++ b/src/Sexy.TodLib/TodCommon.h @@ -93,64 +93,64 @@ float TodCurveInvCircle(float theTime); float TodCurveEvaluate(float theTime, float thePositionStart, float thePositionEnd, TodCurves theCurve); float TodCurveEvaluateClamped(float theTime, float thePositionStart, float thePositionEnd, TodCurves theCurve); float TodAnimateCurveFloatTime(float theTimeStart, - float theTimeEnd, - float theTimeAge, - float thePositionStart, - float thePositionEnd, - TodCurves theCurve); + float theTimeEnd, + float theTimeAge, + float thePositionStart, + float thePositionEnd, + TodCurves theCurve); float TodAnimateCurveFloat( - int theTimeStart, int theTimeEnd, int theTimeAge, float thePositionStart, float thePositionEnd, TodCurves theCurve); + int theTimeStart, int theTimeEnd, int theTimeAge, float thePositionStart, float thePositionEnd, TodCurves theCurve); int TodAnimateCurve( - int theTimeStart, int theTimeEnd, int theTimeAge, int thePositionStart, int thePositionEnd, TodCurves theCurve); + int theTimeStart, int theTimeEnd, int theTimeAge, int thePositionStart, int thePositionEnd, TodCurves theCurve); void TodScaleTransformMatrix(SexyMatrix3 &m, float x, float y, float theScaleX, float theScaleY); void TodScaleRotateTransformMatrix(SexyMatrix3 &m, float x, float y, float rad, float theScaleX, float theScaleY); void SexyMatrix3ExtractScale(const SexyMatrix3 &m, float &theScaleX, float &theScaleY); void SexyMatrix3Translation(SexyMatrix3 &m, float x, float y); -void SexyMatrix3Transpose(const SexyMatrix3 &m, SexyMatrix3 &r); // r = m ^ T -void SexyMatrix3Inverse(const SexyMatrix3 &m, SexyMatrix3 &r); // r = m ^ -1 +void SexyMatrix3Transpose(const SexyMatrix3 &m, SexyMatrix3 &r); // r = m ^ T +void SexyMatrix3Inverse(const SexyMatrix3 &m, SexyMatrix3 &r); // r = m ^ -1 void SexyMatrix3Multiply(SexyMatrix3 &m, const SexyMatrix3 &l, const SexyMatrix3 &r); // m = l ¡Á r bool TodIsPointInPolygon(const SexyVector2 *thePolygonPoint, - int theNumberPolygonPoints, - const SexyVector2 &theCheckPoint); + int theNumberPolygonPoints, + const SexyVector2 &theCheckPoint); void TodDrawString(Graphics *g, - const SexyString &theText, - int thePosX, - int thePosY, - Font *theFont, - const Color &theColor, - DrawStringJustification theJustification); + const SexyString &theText, + int thePosX, + int thePosY, + Font *theFont, + const Color &theColor, + DrawStringJustification theJustification); void TodDrawStringMatrix( - Graphics *g, const Font *theFont, const SexyMatrix3 &theMatrix, const SexyString &theString, const Color &theColor); + Graphics *g, Font *theFont, const SexyMatrix3 &theMatrix, const SexyString &theString, const Color &theColor); void TodDrawImageScaledF(Graphics *g, Image *theImage, float thePosX, float thePosY, float theScaleX, float theScaleY); void TodDrawImageCenterScaledF( - Graphics *g, Image *theImage, float thePosX, float thePosY, float theScaleX, float theScaleY); + Graphics *g, Image *theImage, float thePosX, float thePosY, float theScaleX, float theScaleY); void TodDrawImageCelF(Graphics *g, Image *theImageStrip, float thePosX, float thePosY, int theCelCol, int theCelRow); void TodDrawImageCelScaled(Graphics *g, - Image *theImageStrip, - int thePosX, - int thePosY, - int theCelCol, - int theCelRow, - float theScaleX, - float theScaleY); + Image *theImageStrip, + int thePosX, + int thePosY, + int theCelCol, + int theCelRow, + float theScaleX, + float theScaleY); void TodDrawImageCelScaledF(Graphics *g, - Image *theImageStrip, - float thePosX, - float thePosY, - int theCelCol, - int theCelRow, - float theScaleX, - float theScaleY); + Image *theImageStrip, + float thePosX, + float thePosY, + int theCelCol, + int theCelRow, + float theScaleX, + float theScaleY); void TodDrawImageCelCenterScaledF(Graphics *g, Image *theImageStrip, float thePosX, float thePosY, int theCelCol, int theCelRow, float theScaleX, float theScaleY); void TodBltMatrix(Graphics *g, - Image *theImage, - const SexyMatrix3 &theTransform, - const Rect &theClipRect, - const Color &theColor, - int theDrawMode, - const Rect &theSrcRect); + Image *theImage, + const SexyMatrix3 &theTransform, + const Rect &theClipRect, + const Color &theColor, + int theDrawMode, + const Rect &theSrcRect); void TodMarkImageForSanding(Image *theImage); void TodSandImageIfNeeded(Image *theImage); void FixPixelsOnAlphaEdgeForBlending(Image *theImage); @@ -158,8 +158,8 @@ uint32_t AverageNearByPixels(MemoryImage *theImage, uint32_t *thePixel, int x, i void Tod_SWTri_AddAllDrawTriFuncs(); SexyString TodReplaceString(const SexyString &theText, - const SexyString &theStringToFind, - const SexyString &theStringToSubstitute); + const SexyString &theStringToFind, + const SexyString &theStringToSubstitute); SexyString TodReplaceNumberString(const SexyString &theText, const SexyString &theStringToFind, int theNumber); int TodSnprintf(char *theBuffer, int theSize, const char *theFormat, ...); int TodVsnprintf(char *theBuffer, int theSize, const char *theFormat, va_list theArgList); @@ -176,15 +176,18 @@ int RandRangeInt(int theMin, int theMax); float RandRangeFloat(float theMin, float theMax); inline char ClampByte(char theNum, char theMin, char theMax) { - return theNum <= theMin ? theMin : theNum >= theMax ? theMax : theNum; + return theNum <= theMin ? theMin : theNum >= theMax ? theMax + : theNum; } inline int ClampInt(int theNum, int theMin, int theMax) { - return theNum <= theMin ? theMin : theNum >= theMax ? theMax : theNum; + return theNum <= theMin ? theMin : theNum >= theMax ? theMax + : theNum; } inline float ClampFloat(float theNum, float theMin, float theMax) { - return theNum <= theMin ? theMin : theNum >= theMax ? theMax : theNum; + return theNum <= theMin ? theMin : theNum >= theMax ? theMax + : theNum; } inline float Distance2D(float x1, float y1, float x2, float y2) { diff --git a/src/SexyAppFramework/Encoding.cpp b/src/SexyAppFramework/Encoding.cpp index 8afa43d..bd1286a 100644 --- a/src/SexyAppFramework/Encoding.cpp +++ b/src/SexyAppFramework/Encoding.cpp @@ -1,88 +1,88 @@ -#include "Encoding.h" -#include "Common.h" - -namespace Sexy -{ -// Convert a UTF-16 byte buffer to UTF-8. Return nullopt if input is not valid UTF-16 -std::optional TryUtf16ToUtf8(const unsigned char *theBytes, std::size_t theByteCount, bool isBigEndian) -{ - int aUnitCount = theByteCount / 2; - std::u16string aWide; - aWide.reserve(aUnitCount); - for (int i = 0; i < aUnitCount; i++) - { - auto aFirst = theBytes[i * 2]; - auto aSecond = theBytes[i * 2 + 1]; - char16_t aUnit = isBigEndian ? (char16_t)((aFirst << 8) | aSecond) : (char16_t)((aSecond << 8) | aFirst); - aWide.push_back(aUnit); - } - - try - { - std::string aResult; - utf8::utf16to8(aWide.begin(), aWide.end(), std::back_inserter(aResult)); - return std::move(aResult); - } - catch (...) - { - return {}; - } -} - -// Decode raw file bytes to UTF-8, auto-detecting the encoding and using ANSI -// as a fallback. Returning nullopt means the input is already valid UTF8 without BOM -std::optional ConvertToUtf8IfNeeded(const std::string &theRaw) -{ - auto aSize = theRaw.size(); - auto aBytes = reinterpret_cast(theRaw.data()); - - // Try UTF-8 first - modern devs should use this - if (aSize >= 3 && aBytes[0] == 0xEF && aBytes[1] == 0xBB && aBytes[2] == 0xBF) - { - // strip BOM if present: EF BB BF - // - used by font descriptors in chinese versions - std::string aUtf8 = theRaw.substr(3); - if (utf8::is_valid(aUtf8)) - { - return aUtf8; - } - return ANSIToUTF8(theRaw); - } - - // UTF-8 without BOM - if (utf8::is_valid(theRaw)) - { - return {}; - } - - // Try UTF-16 - if (aSize >= 2) - { // need at least 2 bytes to make one char16 - // UTF-16 with BOM - if (aBytes[0] == 0xFF && aBytes[1] == 0xFE) - { - // LE - the chinese version of the original game uses this - auto aMaybeUtf16 = TryUtf16ToUtf8(aBytes + 2, aSize - 2, false); - if (aMaybeUtf16) - { - return std::move(*aMaybeUtf16); - } - } - - if (aBytes[0] == 0xFE && aBytes[1] == 0xFF) - { - // BE - auto aMaybeUtf16 = TryUtf16ToUtf8(aBytes + 2, aSize - 2, true); - if (aMaybeUtf16) - { - return std::move(*aMaybeUtf16); - } - } - - // we don't handle UTF-16 without BOM for now - } - - // Fallback - this is what the english version uses - return ANSIToUTF8(theRaw); -} -} // namespace Sexy +#include "Encoding.h" +#include "Common.h" + +namespace Sexy +{ +// Convert a UTF-16 byte buffer to UTF-8. Return nullopt if input is not valid UTF-16 +std::optional TryUtf16ToUtf8(const unsigned char *theBytes, std::size_t theByteCount, bool isBigEndian) +{ + int aUnitCount = theByteCount / 2; + std::u16string aWide; + aWide.reserve(aUnitCount); + for (int i = 0; i < aUnitCount; i++) + { + auto aFirst = theBytes[i * 2]; + auto aSecond = theBytes[i * 2 + 1]; + char16_t aUnit = isBigEndian ? (char16_t)((aFirst << 8) | aSecond) : (char16_t)((aSecond << 8) | aFirst); + aWide.push_back(aUnit); + } + + try + { + std::string aResult; + utf8::utf16to8(aWide.begin(), aWide.end(), std::back_inserter(aResult)); + return std::move(aResult); + } + catch (...) + { + return {}; + } +} + +// Decode raw file bytes to UTF-8, auto-detecting the encoding and using ANSI +// as a fallback. Returning nullopt means the input is already valid UTF8 without BOM +std::optional ConvertToUtf8IfNeeded(const std::string &theRaw) +{ + auto aSize = theRaw.size(); + auto aBytes = reinterpret_cast(theRaw.data()); + + // Try UTF-8 first - modern devs should use this + if (aSize >= 3 && aBytes[0] == 0xEF && aBytes[1] == 0xBB && aBytes[2] == 0xBF) + { + // strip BOM if present: EF BB BF + // - used by font descriptors in chinese versions + std::string aUtf8 = theRaw.substr(3); + if (utf8::is_valid(aUtf8)) + { + return aUtf8; + } + return ANSIToUTF8(theRaw); + } + + // UTF-8 without BOM + if (utf8::is_valid(theRaw)) + { + return {}; + } + + // Try UTF-16 + if (aSize >= 2) + { // need at least 2 bytes to make one char16 + // UTF-16 with BOM + if (aBytes[0] == 0xFF && aBytes[1] == 0xFE) + { + // LE - the chinese version of the original game uses this + auto aMaybeUtf16 = TryUtf16ToUtf8(aBytes + 2, aSize - 2, false); + if (aMaybeUtf16) + { + return std::move(*aMaybeUtf16); + } + } + + if (aBytes[0] == 0xFE && aBytes[1] == 0xFF) + { + // BE + auto aMaybeUtf16 = TryUtf16ToUtf8(aBytes + 2, aSize - 2, true); + if (aMaybeUtf16) + { + return std::move(*aMaybeUtf16); + } + } + + // we don't handle UTF-16 without BOM for now + } + + // Fallback - this is what the english version uses + return ANSIToUTF8(theRaw); +} +} // namespace Sexy diff --git a/src/SexyAppFramework/Encoding.h b/src/SexyAppFramework/Encoding.h index 8f4b8c9..babfd5f 100644 --- a/src/SexyAppFramework/Encoding.h +++ b/src/SexyAppFramework/Encoding.h @@ -1,16 +1,16 @@ -#pragma once - -#include -#include - -namespace Sexy -{ - -// Convert a UTF-16 byte buffer to UTF-8. Return nullopt if input is not valid UTF-16 -std::optional TryUtf16ToUtf8(const unsigned char *theBytes, std::size_t theByteCount, bool isBigEndian); - -// Convert a buffer to UTF-8 (wihout BOM) if it's not already. Return nullopt if the input is already UTF-8 (without BOM) -// Supports UTF-16 LE/BE with BOM. Fallback to ANSI -std::optional ConvertToUtf8IfNeeded(const std::string &theRaw); - -} // namespace Sexy +#pragma once + +#include +#include + +namespace Sexy +{ + +// Convert a UTF-16 byte buffer to UTF-8. Return nullopt if input is not valid UTF-16 +std::optional TryUtf16ToUtf8(const unsigned char *theBytes, std::size_t theByteCount, bool isBigEndian); + +// Convert a buffer to UTF-8 (wihout BOM) if it's not already. Return nullopt if the input is already UTF-8 (without BOM) +// Supports UTF-16 LE/BE with BOM. Fallback to ANSI +std::optional ConvertToUtf8IfNeeded(const std::string &theRaw); + +} // namespace Sexy diff --git a/src/SexyAppFramework/ImageFont.cpp b/src/SexyAppFramework/ImageFont.cpp index 57884c5..ce6ca6b 100644 --- a/src/SexyAppFramework/ImageFont.cpp +++ b/src/SexyAppFramework/ImageFont.cpp @@ -3,6 +3,7 @@ #include "Image.h" #include "SexyAppBase.h" #include "MemoryImage.h" +#include "RenderCommand.h" using namespace Sexy; @@ -104,16 +105,15 @@ FontLayer::FontLayer(FontData *theFontData) } FontLayer::FontLayer(const FontLayer &theFontLayer) - : mFontData(theFontLayer.mFontData), mRequiredTags(theFontLayer.mRequiredTags), - mExcludedTags(theFontLayer.mExcludedTags), mImage(theFontLayer.mImage), mDrawMode(theFontLayer.mDrawMode), - mOffset(theFontLayer.mOffset), mSpacing(theFontLayer.mSpacing), mMinPointSize(theFontLayer.mMinPointSize), - mMaxPointSize(theFontLayer.mMaxPointSize), mPointSize(theFontLayer.mPointSize), mAscent(theFontLayer.mAscent), - mAscentPadding(theFontLayer.mAscentPadding), mHeight(theFontLayer.mHeight), - mDefaultHeight(theFontLayer.mDefaultHeight), mColorMult(theFontLayer.mColorMult), - mColorAdd(theFontLayer.mColorAdd), mLineSpacingOffset(theFontLayer.mLineSpacingOffset), - mBaseOrder(theFontLayer.mBaseOrder), mCharData(theFontLayer.mCharData) + : mFontData(theFontLayer.mFontData), mRequiredTags(theFontLayer.mRequiredTags), + mExcludedTags(theFontLayer.mExcludedTags), mImage(theFontLayer.mImage), mDrawMode(theFontLayer.mDrawMode), + mOffset(theFontLayer.mOffset), mSpacing(theFontLayer.mSpacing), mMinPointSize(theFontLayer.mMinPointSize), + mMaxPointSize(theFontLayer.mMaxPointSize), mPointSize(theFontLayer.mPointSize), mAscent(theFontLayer.mAscent), + mAscentPadding(theFontLayer.mAscentPadding), mHeight(theFontLayer.mHeight), + mDefaultHeight(theFontLayer.mDefaultHeight), mColorMult(theFontLayer.mColorMult), + mColorAdd(theFontLayer.mColorAdd), mLineSpacingOffset(theFontLayer.mLineSpacingOffset), + mBaseOrder(theFontLayer.mBaseOrder), mCharData(theFontLayer.mCharData) { - } CharData *FontLayer::GetCharData(SexyChar value) { @@ -202,9 +202,9 @@ bool FontData::GetColorFromDataElement(DataElement *theElement, Color &theColor) return false; theColor = Color((int)(aFactorVector[0] * 255), - (int)(aFactorVector[1] * 255), - (int)(aFactorVector[2] * 255), - (int)(aFactorVector[3] * 255)); + (int)(aFactorVector[1] * 255), + (int)(aFactorVector[2] * 255), + (int)(aFactorVector[3] * 255)); return true; } @@ -283,8 +283,8 @@ bool FontData::HandleCommand(const ListDataElement &theParams) IntVector aWidthsVector; if ((!theParams.mElementVector[1]->mIsList) && - (DataToIntVector(theParams.mElementVector[2], &aRectIntVector)) && (aRectIntVector.size() == 4) && - (DataToIntVector(theParams.mElementVector[3], &aWidthsVector))) + (DataToIntVector(theParams.mElementVector[2], &aRectIntVector)) && (aRectIntVector.size() == 4) && + (DataToIntVector(theParams.mElementVector[3], &aWidthsVector))) { std::string aDefineName = StringToUpper(((SingleDataElement *)theParams.mElementVector[1])->mString); @@ -336,7 +336,7 @@ bool FontData::HandleCommand(const ListDataElement &theParams) int aPointSize; if ((!theParams.mElementVector[1]->mIsList) && - (StringToInt(((SingleDataElement *)theParams.mElementVector[1])->mString, &aPointSize))) + (StringToInt(((SingleDataElement *)theParams.mElementVector[1])->mString, &aPointSize))) { mDefaultPointSize = aPointSize; } @@ -354,7 +354,7 @@ bool FontData::HandleCommand(const ListDataElement &theParams) StringVector aToVector; if ((DataToStringVector(theParams.mElementVector[1], &aFromVector)) && - (DataToStringVector(theParams.mElementVector[2], &aToVector))) + (DataToStringVector(theParams.mElementVector[2], &aToVector))) { if (aFromVector.size() == aToVector.size()) { @@ -431,7 +431,7 @@ bool FontData::HandleCommand(const ListDataElement &theParams) StringVector aStringVector; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && - (DataToStringVector(theParams.mElementVector[2], &aStringVector))) + (DataToStringVector(theParams.mElementVector[2], &aStringVector))) { for (uint32_t i = 0; i < aStringVector.size(); i++) aLayer->mRequiredTags.push_back(StringToUpper(aStringVector[i])); @@ -450,7 +450,7 @@ bool FontData::HandleCommand(const ListDataElement &theParams) StringVector aStringVector; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && - (DataToStringVector(theParams.mElementVector[2], &aStringVector))) + (DataToStringVector(theParams.mElementVector[2], &aStringVector))) { for (uint32_t i = 0; i < aStringVector.size(); i++) aLayer->mExcludedTags.push_back(StringToUpper(aStringVector[i])); @@ -467,13 +467,13 @@ bool FontData::HandleCommand(const ListDataElement &theParams) { FontLayer *aLayer; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && (!theParams.mElementVector[2]->mIsList) && - (!theParams.mElementVector[3]->mIsList)) + (!theParams.mElementVector[3]->mIsList)) { int aMinPointSize; int aMaxPointSize; if ((StringToInt(((SingleDataElement *)theParams.mElementVector[2])->mString, &aMinPointSize)) && - (StringToInt(((SingleDataElement *)theParams.mElementVector[3])->mString, &aMaxPointSize))) + (StringToInt(((SingleDataElement *)theParams.mElementVector[3])->mString, &aMaxPointSize))) { aLayer->mMinPointSize = aMinPointSize; aLayer->mMaxPointSize = aMaxPointSize; @@ -537,7 +537,7 @@ bool FontData::HandleCommand(const ListDataElement &theParams) std::string aFileNameString; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && - (DataToString(theParams.mElementVector[2], &aFileNameString))) + (DataToString(theParams.mElementVector[2], &aFileNameString))) { std::string aFileName = GetPathFrom(aFileNameString, GetFileDir(mSourceFile)); @@ -571,7 +571,7 @@ bool FontData::HandleCommand(const ListDataElement &theParams) { int anDrawMode; if ((StringToInt(((SingleDataElement *)theParams.mElementVector[2])->mString, &anDrawMode)) && - (anDrawMode >= 0) && (anDrawMode <= 1)) + (anDrawMode >= 0) && (anDrawMode <= 1)) { aLayer->mDrawMode = anDrawMode; } @@ -687,7 +687,7 @@ bool FontData::HandleCommand(const ListDataElement &theParams) IntVector anOffset; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && - (DataToIntVector(theParams.mElementVector[2], &anOffset)) && (anOffset.size() == 2)) + (DataToIntVector(theParams.mElementVector[2], &anOffset)) && (anOffset.size() == 2)) { aLayer->mOffset.mX = anOffset[0]; aLayer->mOffset.mY = anOffset[1]; @@ -707,8 +707,8 @@ bool FontData::HandleCommand(const ListDataElement &theParams) IntVector aCharWidthsVector; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && - (DataToStringVector(theParams.mElementVector[2], &aCharsVector)) && - (DataToIntVector(theParams.mElementVector[3], &aCharWidthsVector))) + (DataToStringVector(theParams.mElementVector[2], &aCharsVector)) && + (DataToIntVector(theParams.mElementVector[3], &aCharWidthsVector))) { if (aCharsVector.size() == aCharWidthsVector.size()) { @@ -770,8 +770,8 @@ bool FontData::HandleCommand(const ListDataElement &theParams) ListDataElement aRectList; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && - (DataToStringVector(theParams.mElementVector[2], &aCharsVector)) && - (DataToList(theParams.mElementVector[3], &aRectList))) + (DataToStringVector(theParams.mElementVector[2], &aCharsVector)) && + (DataToList(theParams.mElementVector[3], &aRectList))) { if (aCharsVector.size() == aRectList.mElementVector.size()) { @@ -785,14 +785,14 @@ bool FontData::HandleCommand(const ListDataElement &theParams) IntVector aRectElement; if (utf8::is_valid(aCharsVector[i]) && - (DataToIntVector(aRectList.mElementVector[i], &aRectElement)) && - (aRectElement.size() == 4)) + (DataToIntVector(aRectList.mElementVector[i], &aRectElement)) && + (aRectElement.size() == 4)) { Rect aRect = Rect(aRectElement[0], aRectElement[1], aRectElement[2], aRectElement[3]); if ((aRect.mX < 0) || (aRect.mY < 0) || (aRect.mX + aRect.mWidth > anImageWidth) || - (aRect.mY + aRect.mHeight > anImageHeight)) + (aRect.mY + aRect.mHeight > anImageHeight)) { Error("Image rectangle out of bounds"); return false; @@ -814,7 +814,7 @@ bool FontData::HandleCommand(const ListDataElement &theParams) for (auto &it : aLayer->mCharData) if (aLayer->mCharData[it.first].mImageRect.mHeight + aLayer->mCharData[it.first].mOffset.mY > aLayer->mDefaultHeight) aLayer->mDefaultHeight = aLayer->mCharData[it.first].mImageRect.mHeight + - aLayer->mCharData[it.first].mOffset.mY; + aLayer->mCharData[it.first].mOffset.mY; } else { @@ -840,8 +840,8 @@ bool FontData::HandleCommand(const ListDataElement &theParams) ListDataElement aRectList; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && - (DataToStringVector(theParams.mElementVector[2], &aCharsVector)) && - (DataToList(theParams.mElementVector[3], &aRectList))) + (DataToStringVector(theParams.mElementVector[2], &aCharsVector)) && + (DataToList(theParams.mElementVector[3], &aRectList))) { if (aCharsVector.size() == aRectList.mElementVector.size()) { @@ -850,7 +850,7 @@ bool FontData::HandleCommand(const ListDataElement &theParams) IntVector aRectElement; if (utf8::is_valid(aCharsVector[i]) && - (DataToIntVector(aRectList.mElementVector[i], &aRectElement)) && (aRectElement.size() == 2)) + (DataToIntVector(aRectList.mElementVector[i], &aRectElement)) && (aRectElement.size() == 2)) { std::string aCharStr = aCharsVector[i]; auto it = aCharStr.begin(); @@ -859,7 +859,7 @@ bool FontData::HandleCommand(const ListDataElement &theParams) while (it != end) aCodepoint = utf8::next(it, end); aLayer->mCharData[aCodepoint].mOffset = - Point(aRectElement[0], aRectElement[1]); + Point(aRectElement[0], aRectElement[1]); } else invalidParamFormat = true; @@ -883,8 +883,8 @@ bool FontData::HandleCommand(const ListDataElement &theParams) IntVector anOffsetsVector; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && - (DataToStringVector(theParams.mElementVector[2], &aPairsVector)) && - (DataToIntVector(theParams.mElementVector[3], &anOffsetsVector))) + (DataToStringVector(theParams.mElementVector[2], &aPairsVector)) && + (DataToIntVector(theParams.mElementVector[3], &anOffsetsVector))) { if (aPairsVector.size() == anOffsetsVector.size()) { @@ -893,7 +893,7 @@ bool FontData::HandleCommand(const ListDataElement &theParams) if (aPairsVector[i].length() == 2) { aLayer->mCharData[aPairsVector[i][0]].mKerningOffsets[aPairsVector[i][1]] = - anOffsetsVector[i]; + anOffsetsVector[i]; } else invalidParamFormat = true; @@ -938,8 +938,8 @@ bool FontData::HandleCommand(const ListDataElement &theParams) IntVector aCharOrdersVector; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && - (DataToStringVector(theParams.mElementVector[2], &aCharsVector)) && - (DataToIntVector(theParams.mElementVector[3], &aCharOrdersVector))) + (DataToStringVector(theParams.mElementVector[2], &aCharsVector)) && + (DataToIntVector(theParams.mElementVector[3], &aCharOrdersVector))) { if (aCharsVector.size() == aCharOrdersVector.size()) { @@ -968,10 +968,10 @@ bool FontData::HandleCommand(const ListDataElement &theParams) else invalidNumParams = true; } - else if (stricmp(aCmd.c_str(), "LayerSetExInfo") == 0) - { - // used in chinese versions, not implemented for now - } + else if (stricmp(aCmd.c_str(), "LayerSetExInfo") == 0) + { + // used in chinese versions, not implemented for now + } else { Error("Unknown Command"); @@ -1053,7 +1053,7 @@ bool FontData::LoadLegacy(Image *theFontImage, const std::string &theFontDescFil while (!feof(aStream)) { - char aBuf[2] = {0, 0}; // needed because fscanf will null terminate the string it reads + char aBuf[2] = { 0, 0 }; // needed because fscanf will null terminate the string it reads char aChar = 0; int aWidth = 0; @@ -1094,8 +1094,8 @@ ActiveFontLayer::ActiveFontLayer() } ActiveFontLayer::ActiveFontLayer(const ActiveFontLayer &theActiveFontLayer) - : mBaseFontLayer(theActiveFontLayer.mBaseFontLayer), mScaledImage(theActiveFontLayer.mScaledImage), - mOwnsImage(theActiveFontLayer.mOwnsImage), mScaledCharImageRects(theActiveFontLayer.mScaledCharImageRects) + : mBaseFontLayer(theActiveFontLayer.mBaseFontLayer), mScaledImage(theActiveFontLayer.mScaledImage), + mOwnsImage(theActiveFontLayer.mOwnsImage), mScaledCharImageRects(theActiveFontLayer.mScaledCharImageRects) { if (mOwnsImage) mScaledImage = (Sexy::Image *)mBaseFontLayer->mFontData->mApp->CopyImage(mScaledImage); @@ -1141,9 +1141,9 @@ ImageFont::ImageFont(Image *theFontImage) } ImageFont::ImageFont(const ImageFont &theImageFont) - : Font(theImageFont), mScale(theImageFont.mScale), mFontData(theImageFont.mFontData), - mPointSize(theImageFont.mPointSize), mTagVector(theImageFont.mTagVector), - mActiveListValid(theImageFont.mActiveListValid), mForceScaledImagesWhite(theImageFont.mForceScaledImagesWhite) + : Font(theImageFont), mScale(theImageFont.mScale), mFontData(theImageFont.mFontData), + mPointSize(theImageFont.mPointSize), mTagVector(theImageFont.mTagVector), + mActiveListValid(theImageFont.mActiveListValid), mForceScaledImagesWhite(theImageFont.mForceScaledImagesWhite) { mFontData->Ref(); @@ -1202,7 +1202,7 @@ void ImageFont::GenerateActiveFontLayers() FontLayer *aFontLayer = &*anItr; if ((mPointSize >= aFontLayer->mMinPointSize) && - ((mPointSize <= aFontLayer->mMaxPointSize) || (aFontLayer->mMaxPointSize == -1))) + ((mPointSize <= aFontLayer->mMaxPointSize) || (aFontLayer->mMaxPointSize == -1))) { bool active = true; @@ -1214,7 +1214,7 @@ void ImageFont::GenerateActiveFontLayers() // Make sure no excluded tags are included for (i = 0; i < mTagVector.size(); i++) if (std::find(aFontLayer->mExcludedTags.begin(), aFontLayer->mExcludedTags.end(), mTagVector[i]) != - aFontLayer->mExcludedTags.end()) + aFontLayer->mExcludedTags.end()) active = false; if (active) @@ -1258,9 +1258,9 @@ void ImageFont::GenerateActiveFontLayers() Rect *anOrigRect = &it.second.mImageRect; Rect aScaledRect(aCurX, - 0, - (int)((anOrigRect->mWidth * aPointSize) / aLayerPointSize), - (int)((anOrigRect->mHeight * aPointSize) / aLayerPointSize)); + 0, + (int)((anOrigRect->mWidth * aPointSize) / aLayerPointSize), + (int)((anOrigRect->mHeight * aPointSize) / aLayerPointSize)); anActiveFontLayer->mScaledCharImageRects[it.first] = aScaledRect; @@ -1283,8 +1283,8 @@ void ImageFont::GenerateActiveFontLayers() { if ((Image *)aFontLayer->mImage != NULL) g.DrawImage(aFontLayer->mImage, - anActiveFontLayer->mScaledCharImageRects[it.first], - it.second.mImageRect); + anActiveFontLayer->mScaledCharImageRects[it.first], + it.second.mImageRect); } if (mForceScaledImagesWhite) @@ -1380,9 +1380,9 @@ int ImageFont::CharWidthKern(uint32_t theChar, uint32_t thePrevChar) if (thePrevChar != 0) { aSpacing = - (anActiveFontLayer->mBaseFontLayer->mSpacing + - anActiveFontLayer->mBaseFontLayer->mCharData[thePrevChar].mKerningOffsets[theChar]) * - mScale; + (anActiveFontLayer->mBaseFontLayer->mSpacing + + anActiveFontLayer->mBaseFontLayer->mCharData[thePrevChar].mKerningOffsets[theChar]) * + mScale; } else aSpacing = 0; @@ -1390,14 +1390,14 @@ int ImageFont::CharWidthKern(uint32_t theChar, uint32_t thePrevChar) else { aCharWidth = - (anActiveFontLayer->mBaseFontLayer->mCharData[theChar].mWidth * aPointSize / aLayerPointSize); + (anActiveFontLayer->mBaseFontLayer->mCharData[theChar].mWidth * aPointSize / aLayerPointSize); if (thePrevChar != 0) { aSpacing = - (anActiveFontLayer->mBaseFontLayer->mSpacing + - anActiveFontLayer->mBaseFontLayer->mCharData[thePrevChar].mKerningOffsets[theChar]) * - aPointSize / aLayerPointSize; + (anActiveFontLayer->mBaseFontLayer->mSpacing + + anActiveFontLayer->mBaseFontLayer->mCharData[thePrevChar].mKerningOffsets[theChar]) * + aPointSize / aLayerPointSize; } else aSpacing = 0; @@ -1420,38 +1420,25 @@ int ImageFont::CharWidth(uint32_t theChar) } std::mutex gRenderCritSec; -static const int POOL_SIZE = 4096; -static RenderCommand gRenderCommandPool[POOL_SIZE]; -static RenderCommand *gRenderTail[256]; -static RenderCommand *gRenderHead[256]; +static RenderCommandList gRenderCommandList; void ImageFont::DrawStringEx(Graphics *g, - int theX, - int theY, - const SexyString &theString, - const Color &theColor, - const Rect *theClipRect, - RectList *theDrawnAreas, - int *theWidth) + int theX, + int theY, + const SexyString &theString, + const Color &theColor, + const Rect *theClipRect, + RectList *theDrawnAreas, + int *theWidth) { auto aLock = std::scoped_lock(gRenderCritSec); - - int aPoolIdx; - - for (aPoolIdx = 0; aPoolIdx < 256; aPoolIdx++) - { - gRenderHead[aPoolIdx] = NULL; - gRenderTail[aPoolIdx] = NULL; - } + gRenderCommandList.Clear(); int aXPos = theX; if (theDrawnAreas != NULL) theDrawnAreas->clear(); - /*if (theDrawnArea != NULL) - *theDrawnArea = Rect(0, 0, 0, 0);*/ - if (!mFontData->mInitialized) { if (theWidth != NULL) @@ -1508,17 +1495,17 @@ void ImageFont::DrawStringEx(Graphics *g, if (aScale == 1.0) { anImageX = aLayerXPos + anActiveFontLayer->mBaseFontLayer->mOffset.mX + - anActiveFontLayer->mBaseFontLayer->mCharData[aChar].mOffset.mX; + anActiveFontLayer->mBaseFontLayer->mCharData[aChar].mOffset.mX; anImageY = - theY - (anActiveFontLayer->mBaseFontLayer->mAscent - anActiveFontLayer->mBaseFontLayer->mOffset.mY - - anActiveFontLayer->mBaseFontLayer->mCharData[aChar].mOffset.mY); + theY - (anActiveFontLayer->mBaseFontLayer->mAscent - anActiveFontLayer->mBaseFontLayer->mOffset.mY - + anActiveFontLayer->mBaseFontLayer->mCharData[aChar].mOffset.mY); aCharWidth = anActiveFontLayer->mBaseFontLayer->mCharData[aChar].mWidth; if (aNextChar != 0) { aSpacing = - anActiveFontLayer->mBaseFontLayer->mSpacing + - anActiveFontLayer->mBaseFontLayer->mCharData[aChar].mKerningOffsets[aNextChar]; + anActiveFontLayer->mBaseFontLayer->mSpacing + + anActiveFontLayer->mBaseFontLayer->mCharData[aChar].mKerningOffsets[aNextChar]; } else aSpacing = 0; @@ -1526,20 +1513,20 @@ void ImageFont::DrawStringEx(Graphics *g, else { anImageX = aLayerXPos + (int)((anActiveFontLayer->mBaseFontLayer->mOffset.mX + - anActiveFontLayer->mBaseFontLayer->mCharData[aChar].mOffset.mX) * - aScale); + anActiveFontLayer->mBaseFontLayer->mCharData[aChar].mOffset.mX) * + aScale); anImageY = theY - (int)((anActiveFontLayer->mBaseFontLayer->mAscent - - anActiveFontLayer->mBaseFontLayer->mOffset.mY - - anActiveFontLayer->mBaseFontLayer->mCharData[aChar].mOffset.mY) * - aScale); + anActiveFontLayer->mBaseFontLayer->mOffset.mY - + anActiveFontLayer->mBaseFontLayer->mCharData[aChar].mOffset.mY) * + aScale); aCharWidth = (anActiveFontLayer->mBaseFontLayer->mCharData[aChar].mWidth * aScale); if (aNextChar != 0) { aSpacing = (int)((anActiveFontLayer->mBaseFontLayer->mSpacing + - anActiveFontLayer->mBaseFontLayer->mCharData[aChar] - .mKerningOffsets[aNextChar]) * - aScale); + anActiveFontLayer->mBaseFontLayer->mCharData[aChar] + .mKerningOffsets[aNextChar]) * + aScale); } else aSpacing = 0; @@ -1547,51 +1534,33 @@ void ImageFont::DrawStringEx(Graphics *g, Color aColor; aColor.mRed = std::min((theColor.mRed * anActiveFontLayer->mBaseFontLayer->mColorMult.mRed / 255) + - anActiveFontLayer->mBaseFontLayer->mColorAdd.mRed, - 255); + anActiveFontLayer->mBaseFontLayer->mColorAdd.mRed, + 255); aColor.mGreen = std::min((theColor.mGreen * anActiveFontLayer->mBaseFontLayer->mColorMult.mGreen / 255) + - anActiveFontLayer->mBaseFontLayer->mColorAdd.mGreen, - 255); + anActiveFontLayer->mBaseFontLayer->mColorAdd.mGreen, + 255); aColor.mBlue = std::min((theColor.mBlue * anActiveFontLayer->mBaseFontLayer->mColorMult.mBlue / 255) + - anActiveFontLayer->mBaseFontLayer->mColorAdd.mBlue, - 255); + anActiveFontLayer->mBaseFontLayer->mColorAdd.mBlue, + 255); aColor.mAlpha = std::min((theColor.mAlpha * anActiveFontLayer->mBaseFontLayer->mColorMult.mAlpha / 255) + - anActiveFontLayer->mBaseFontLayer->mColorAdd.mAlpha, - 255); + anActiveFontLayer->mBaseFontLayer->mColorAdd.mAlpha, + 255); int anOrder = anActiveFontLayer->mBaseFontLayer->mBaseOrder + - anActiveFontLayer->mBaseFontLayer->GetCharData(aChar)->mOrder; + anActiveFontLayer->mBaseFontLayer->GetCharData(aChar)->mOrder; - if (aCurPoolIdx >= POOL_SIZE) + RenderCommand *aRenderCommand = gRenderCommandList.PushWithOrder(anOrder); + if (!aRenderCommand) + { break; - - RenderCommand *aRenderCommand = &gRenderCommandPool[aCurPoolIdx++]; + } aRenderCommand->mImage = anActiveFontLayer->mScaledImage; aRenderCommand->mColor = aColor; - aRenderCommand->mDest[0] = anImageX; - aRenderCommand->mDest[1] = anImageY; - aRenderCommand->mSrc[0] = anActiveFontLayer->mScaledCharImageRects[aChar].mX; - aRenderCommand->mSrc[1] = anActiveFontLayer->mScaledCharImageRects[aChar].mY; - aRenderCommand->mSrc[2] = anActiveFontLayer->mScaledCharImageRects[aChar].mWidth; - aRenderCommand->mSrc[3] = anActiveFontLayer->mScaledCharImageRects[aChar].mHeight; + aRenderCommand->mDestX = anImageX; + aRenderCommand->mDestY = anImageY; + aRenderCommand->mSrc = anActiveFontLayer->mScaledCharImageRects[aChar]; aRenderCommand->mMode = anActiveFontLayer->mBaseFontLayer->mDrawMode; - aRenderCommand->mNext = NULL; - - int anOrderIdx = std::min(std::max(anOrder + 128, 0), 255); - - if (gRenderTail[anOrderIdx] == NULL) - { - gRenderTail[anOrderIdx] = aRenderCommand; - gRenderHead[anOrderIdx] = aRenderCommand; - } - else - { - gRenderTail[anOrderIdx]->mNext = aRenderCommand; - gRenderTail[anOrderIdx] = aRenderCommand; - } - - //aRenderCommandMap.insert(RenderCommandMap::value_type(aPriority, aRenderCommand)); /*int anOldDrawMode = g->GetDrawMode(); if (anActiveFontLayer->mBaseFontLayer->mDrawMode != -1) @@ -1606,9 +1575,9 @@ void ImageFont::DrawStringEx(Graphics *g, if (theDrawnAreas != NULL) { Rect aDestRect = Rect(anImageX, - anImageY, - anActiveFontLayer->mScaledCharImageRects[aChar].mWidth, - anActiveFontLayer->mScaledCharImageRects[aChar].mHeight); + anImageY, + anActiveFontLayer->mScaledCharImageRects[aChar].mWidth, + anActiveFontLayer->mScaledCharImageRects[aChar].mHeight); theDrawnAreas->push_back(aDestRect); @@ -1653,51 +1622,25 @@ void ImageFont::DrawStringEx(Graphics *g, *theWidth = aCurXPos - theX; Color anOrigColor = g->GetColor(); - - for (aPoolIdx = 0; aPoolIdx < 256; aPoolIdx++) + for (const auto &command : gRenderCommandList) { - RenderCommand *aRenderCommand = gRenderHead[aPoolIdx]; - - while (aRenderCommand != NULL) + int anOldDrawMode = g->GetDrawMode(); + if (command.mMode != -1) + { + g->SetDrawMode(command.mMode); + } + g->SetColor(command.mColor); + if (command.mImage) { - int anOldDrawMode = g->GetDrawMode(); - if (aRenderCommand->mMode != -1) - g->SetDrawMode(aRenderCommand->mMode); - g->SetColor(Color(aRenderCommand->mColor)); - if (aRenderCommand->mImage != NULL) - g->DrawImage(aRenderCommand->mImage, - aRenderCommand->mDest[0], - aRenderCommand->mDest[1], - Rect(aRenderCommand->mSrc[0], - aRenderCommand->mSrc[1], - aRenderCommand->mSrc[2], - aRenderCommand->mSrc[3])); - g->SetDrawMode(anOldDrawMode); - - aRenderCommand = aRenderCommand->mNext; + g->DrawImage(command.mImage, + command.mDestX, + command.mDestY, + command.mSrc); } + g->SetDrawMode(anOldDrawMode); } g->SetColor(anOrigColor); - - /*RenderCommandMap::iterator anItr = aRenderCommandMap.begin(); - while (anItr != aRenderCommandMap.end()) - { - RenderCommand* aRenderCommand = &anItr->second; - - int anOldDrawMode = g->GetDrawMode(); - if (aRenderCommand->mMode != -1) - g->SetDrawMode(aRenderCommand->mMode); - Color anOrigColor = g->GetColor(); - g->SetColor(aRenderCommand->mColor); - if (aRenderCommand->mImage != NULL) - g->DrawImage(aRenderCommand->mImage, aRenderCommand->mDest.mX, aRenderCommand->mDest.mY, aRenderCommand->mSrc); - g->SetColor(anOrigColor); - g->SetDrawMode(anOldDrawMode); - - ++anItr; - }*/ - g->SetColorizeImages(colorizeImages); } @@ -1710,7 +1653,7 @@ SexyChar ImageFont::GetMappedChar(uint32_t value) } void ImageFont::DrawString( - Graphics *g, int theX, int theY, const SexyString &theString, const Color &theColor, const Rect &theClipRect) + Graphics *g, int theX, int theY, const SexyString &theString, const Color &theColor, const Rect &theClipRect) { DrawStringEx(g, theX, theY, theString, theColor, &theClipRect, NULL, NULL); } diff --git a/src/SexyAppFramework/ImageFont.h b/src/SexyAppFramework/ImageFont.h index 2d840af..11014f3 100644 --- a/src/SexyAppFramework/ImageFont.h +++ b/src/SexyAppFramework/ImageFont.h @@ -1,12 +1,12 @@ #ifndef __IMAGEFONT_H__ #define __IMAGEFONT_H__ +#include + #include "Font.h" #include "DescParser.h" #include "SharedImage.h" -#include - namespace Sexy { @@ -48,9 +48,9 @@ class FontLayer int mMaxPointSize; int mPointSize; int mAscent; - int mAscentPadding; // How much space is above the avg uppercase char - int mHeight; // - int mDefaultHeight; // Max height of font character image rects + int mAscentPadding; // How much space is above the avg uppercase char + int mHeight; // + int mDefaultHeight; // Max height of font character image rects int mLineSpacingOffset; // This plus height should get added between lines int mBaseOrder; @@ -114,19 +114,6 @@ class ActiveFontLayer typedef std::list ActiveFontLayerList; -class RenderCommand -{ - public: - Image *mImage; - int mDest[2]; - int mSrc[4]; - int mMode; - Color mColor; - RenderCommand *mNext; -}; - -typedef std::multimap RenderCommandMap; - class ImageFont : public Font { public: @@ -142,13 +129,13 @@ class ImageFont : public Font public: virtual void GenerateActiveFontLayers(); virtual void DrawStringEx(Graphics *g, - int theX, - int theY, - const SexyString &theString, - const Color &theColor, - const Rect *theClipRect, - RectList *theDrawnAreas, - int *theWidth); + int theX, + int theY, + const SexyString &theString, + const Color &theColor, + const Rect *theClipRect, + RectList *theDrawnAreas, + int *theWidth); SexyChar GetMappedChar(uint32_t value); public: @@ -165,7 +152,7 @@ class ImageFont : public Font virtual int CharWidthKern(uint32_t theChar, uint32_t thePrevChar); virtual int StringWidth(const SexyString &theString); virtual void DrawString( - Graphics *g, int theX, int theY, const SexyString &theString, const Color &theColor, const Rect &theClipRect); + Graphics *g, int theX, int theY, const SexyString &theString, const Color &theColor, const Rect &theClipRect); virtual Font *Duplicate(); @@ -183,4 +170,4 @@ class ImageFont : public Font } // namespace Sexy -#endif //__IMAGEFONT_H__ \ No newline at end of file +#endif //__IMAGEFONT_H__ diff --git a/src/SexyAppFramework/Platform.h b/src/SexyAppFramework/Platform.h index 6cf249e..de0320c 100644 --- a/src/SexyAppFramework/Platform.h +++ b/src/SexyAppFramework/Platform.h @@ -1,42 +1,42 @@ -#pragma once - -// Use this include instead of directly -// to avoid conflicts - -#ifdef _WIN32 -#include - -// NOTE: this comment exists to ensure formatters don't put -// above , which causes a very obsecure error - -#include -#include -#include - -// Unfuck windows - -#undef _WIN32_WINNT -#undef WIN32_LEAN_AND_MEAN - -#define WIN32_LEAN_AND_MEAN -#define _WIN32_WINNT 0x0500 -#undef _UNICODE -#undef UNICODE - -#ifdef LoadImage -#undef LoadImage // Windows, i fucking hate you -Electr0Gunner -#endif - -#endif - -#ifndef NOMINMAX -#define NOMINMAX -#endif - -#ifdef max -#undef max -#endif - -#ifdef min -#undef min -#endif +#pragma once + +// Use this include instead of directly +// to avoid conflicts + +#ifdef _WIN32 +#include + +// NOTE: this comment exists to ensure formatters don't put +// above , which causes a very obsecure error + +#include +#include +#include + +// Unfuck windows + +#undef _WIN32_WINNT +#undef WIN32_LEAN_AND_MEAN + +#define WIN32_LEAN_AND_MEAN +#define _WIN32_WINNT 0x0500 +#undef _UNICODE +#undef UNICODE + +#ifdef LoadImage +#undef LoadImage // Windows, i fucking hate you -Electr0Gunner +#endif + +#endif + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifdef max +#undef max +#endif + +#ifdef min +#undef min +#endif diff --git a/src/SexyAppFramework/RenderCommand.h b/src/SexyAppFramework/RenderCommand.h new file mode 100644 index 0000000..c599d3b --- /dev/null +++ b/src/SexyAppFramework/RenderCommand.h @@ -0,0 +1,160 @@ +#pragma once + +#include +#include "Rect.h" +#include "Color.h" + +namespace Sexy +{ + +class Image; + +class RenderCommand +{ + public: + Image *mImage{}; + int mDestX; + int mDestY; + Rect mSrc; + int mMode = -1; + Color mColor{}; + RenderCommand *mNext{}; +}; + +class RenderCommandList +{ + static constexpr int LIST_SIZE = 256; + + class List + { + public: + RenderCommand *mHead{}; + RenderCommand *mTail{}; + }; + using ListArray = std::array; + + class iterator + { + friend class RenderCommandList; + + public: + RenderCommand &operator*() const + { + return *mCurrent; + } + RenderCommand *operator->() const + { + return mCurrent; + } + // pre increment + iterator &operator++() + { + if (mOrder >= LIST_SIZE) + { + return *this; // reached end + } + if (mCurrent) + { + mCurrent = mCurrent->mNext; + } + while (!mCurrent) + { + if (mOrder < LIST_SIZE) + { + ++mOrder; + } + if (mOrder >= LIST_SIZE) + { + return *this; // reached end + } + mCurrent = mLists[mOrder].mHead; + } + return *this; + } + // post increment + iterator operator++(int) + { + iterator old = *this; + ++(*this); + return old; + } + friend bool operator==(const iterator &a, const iterator &b) + { + return a.mOrder == b.mOrder && a.mCurrent == b.mCurrent; + } + friend bool operator!=(const iterator &a, const iterator &b) + { + return !(a == b); + } + + private: + iterator(ListArray &lists, int order) : mLists(lists), mOrder(order) + { + if (order >= 0 && order < LIST_SIZE) + { + mCurrent = mLists[order].mHead; + } + else + { + mCurrent = nullptr; + } + } + ListArray &mLists; + int mOrder; + RenderCommand *mCurrent; + }; + + public: + void Clear() + { + mLists = {}; + mBufferNextIdx = 0; + } + RenderCommand *PushWithOrder(int order) + { + auto *command = Allocate(); + if (command) + { + int orderIdx = std::min(std::max(order + 128, 0), 255); + auto &list = mLists[orderIdx]; + if (list.mTail) + { + list.mTail->mNext = command; + list.mTail = command; + } + else + { + list.mHead = command; + list.mTail = command; + } + } + return command; + } + iterator begin() + { + iterator it(mLists, -1); + ++it; // advance to first element + return it; + } + iterator end() + { + return { mLists, LIST_SIZE }; + } + + private: + RenderCommand *Allocate() + { + if (mBufferNextIdx >= mBuffer.size()) + { + return nullptr; + } + auto *command = &mBuffer[mBufferNextIdx++]; + new (command) RenderCommand; + return command; + } + std::array mBuffer{}; + int mBufferNextIdx{}; + ListArray mLists{}; +}; + +} // namespace Sexy diff --git a/src/SexyAppFramework/SysFont.cpp b/src/SexyAppFramework/SysFont.cpp index 99be1b2..396fa1f 100644 --- a/src/SexyAppFramework/SysFont.cpp +++ b/src/SexyAppFramework/SysFont.cpp @@ -185,6 +185,7 @@ SysFont::SysFont(const SysFont &theSysFont) mFontData = theSysFont.mFontData; mBold = theSysFont.mBold; mItalic = theSysFont.mItalic; + mUnderlined = theSysFont.mUnderlined; mDrawShadow = false; } @@ -217,7 +218,7 @@ int SysFont::StringWidth(const SexyString &theString) void SysFont::DrawString( Graphics *g, int theX, int theY, const SexyString &theString, const Color &theColor, const Rect &theClipRect) { - if (mFontData == nullptr) + if (mFontData == nullptr || !mFontData->mFace) return; int posX = theX; int posY = theY; @@ -252,7 +253,7 @@ void SysFont::DrawString( mFontData->mAtlas.mAtlas, mFontData->mAtlas.mWidth, mFontData->mAtlas.mHeight, - Rect(aDrawX, aDrawY, aGlyph.mWidth, aGlyph.mHeight), + Rect(aDrawX + g->mTransX, aDrawY - mAscent + g->mTransY, aGlyph.mWidth, aGlyph.mHeight), Rect(aGlyph.mX, aGlyph.mY, aGlyph.mWidth, aGlyph.mHeight), theClipRect, theColor, @@ -278,7 +279,8 @@ void SysFont::DrawString( mFontData->mAtlas.mAtlas, mFontData->mAtlas.mWidth, mFontData->mAtlas.mHeight, - Rect(aDrawX + g->mTransX + 1, aDrawY - mAscent + 1 + g->mTransY, aGlyph.mWidth, aGlyph.mHeight), + Rect(aDrawX + g->mTransX + 1, + aDrawY - mAscent + 1 + g->mTransY, aGlyph.mWidth, aGlyph.mHeight), Rect(aGlyph.mX, aGlyph.mY, aGlyph.mWidth, aGlyph.mHeight), theClipRect, theColor,