From c79ddd0d355c9ccf818542fdbd19b83124f8a1e7 Mon Sep 17 00:00:00 2001 From: elasota Date: Sat, 18 Jan 2020 18:20:16 -0500 Subject: [PATCH] Add text anti-aliasing, disable arcade mode --- Aerofoil/GpFontHandler_FreeType2.cpp | 78 +++++++-- GpApp/Banner.cpp | 6 +- GpApp/ColorUtils.cpp | 2 +- GpApp/Coordinates.cpp | 6 +- GpApp/DialogUtils.cpp | 4 +- GpApp/GameOver.cpp | 4 +- GpApp/GliderDefines.h | 2 +- GpApp/HighScores.cpp | 30 ++-- GpApp/Input.cpp | 2 +- GpApp/MainWindow.cpp | 2 +- GpApp/Music.cpp | 8 +- GpApp/Room.cpp | 4 +- GpApp/Scoreboard.cpp | 28 ++-- GpApp/Sound.cpp | 158 +++++++++++++++++- GpApp/WindowUtils.cpp | 2 +- PortabilityLayer/AntiAliasTable.cpp | 56 +++++++ PortabilityLayer/AntiAliasTable.h | 16 ++ PortabilityLayer/FontManager.cpp | 16 +- PortabilityLayer/FontManager.h | 4 +- PortabilityLayer/FontRenderer.cpp | 29 ++-- PortabilityLayer/FontRenderer.h | 2 +- PortabilityLayer/HostFont.h | 2 +- PortabilityLayer/MenuManager.cpp | 12 +- PortabilityLayer/PLButtonWidget.cpp | 2 +- PortabilityLayer/PLLabelWidget.cpp | 2 +- PortabilityLayer/PLQDraw.cpp | 73 ++++++-- PortabilityLayer/PLRadioButtonWidget.cpp | 2 +- PortabilityLayer/PLResourceManager.cpp | 72 +++++++- PortabilityLayer/PLSound.cpp | 31 +--- PortabilityLayer/PLSound.h | 2 +- PortabilityLayer/PortabilityLayer.vcxproj | 2 + .../PortabilityLayer.vcxproj.filters | 6 + PortabilityLayer/QDGraf.cpp | 4 + PortabilityLayer/QDGraf.h | 14 +- PortabilityLayer/QDStandardPalette.cpp | 40 ++++- PortabilityLayer/QDStandardPalette.h | 15 +- PortabilityLayer/RGBAColor.h | 12 ++ PortabilityLayer/RenderedFont.h | 1 + PortabilityLayer/WaveFormat.h | 6 +- gpr2gpa/gpr2gpa.cpp | 17 +- 40 files changed, 615 insertions(+), 159 deletions(-) create mode 100644 PortabilityLayer/AntiAliasTable.cpp create mode 100644 PortabilityLayer/AntiAliasTable.h diff --git a/Aerofoil/GpFontHandler_FreeType2.cpp b/Aerofoil/GpFontHandler_FreeType2.cpp index ce55d41..e853933 100644 --- a/Aerofoil/GpFontHandler_FreeType2.cpp +++ b/Aerofoil/GpFontHandler_FreeType2.cpp @@ -39,7 +39,7 @@ class GpFont_FreeType2 final : public PortabilityLayer::HostFont { public: void Destroy() override; - GpFontRenderedGlyph_FreeType2 *Render(uint32_t unicodeCodePoint, unsigned int size) override; + GpFontRenderedGlyph_FreeType2 *Render(uint32_t unicodeCodePoint, unsigned int size, bool aa) override; bool GetLineSpacing(unsigned int size, int32_t &outSpacing) override; static GpFont_FreeType2 *Create(const FT_StreamRec_ &streamRec, PortabilityLayer::IOStream *stream); @@ -106,7 +106,7 @@ void GpFont_FreeType2::Destroy() free(this); } -GpFontRenderedGlyph_FreeType2 *GpFont_FreeType2::Render(uint32_t unicodeCodePoint, unsigned int size) +GpFontRenderedGlyph_FreeType2 *GpFont_FreeType2::Render(uint32_t unicodeCodePoint, unsigned int size, bool aa) { if (m_currentSize != size) { @@ -120,16 +120,39 @@ GpFontRenderedGlyph_FreeType2 *GpFont_FreeType2::Render(uint32_t unicodeCodePoin if (!glyphIndex) return nullptr; - if (FT_Load_Glyph(m_face, glyphIndex, FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO) != 0) + FT_Int32 loadFlags = 0; + FT_Render_Mode renderMode = FT_RENDER_MODE_NORMAL; + + if (aa) + { + renderMode = FT_RENDER_MODE_NORMAL; + loadFlags = FT_LOAD_TARGET_NORMAL; + } + else + { + loadFlags = FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO; + renderMode = FT_RENDER_MODE_MONO; + } + + if (FT_Load_Glyph(m_face, glyphIndex, loadFlags) != 0) return nullptr; - if (FT_Render_Glyph(m_face->glyph, FT_RENDER_MODE_MONO) != 0) + if (FT_Render_Glyph(m_face->glyph, renderMode) != 0) return nullptr; const FT_GlyphSlot glyph = m_face->glyph; - if (glyph->bitmap.pixel_mode != FT_PIXEL_MODE_MONO) - return nullptr; // ???? + if (aa == false && glyph->bitmap.pixel_mode != FT_PIXEL_MODE_MONO) + return nullptr; + + if (aa == true) + { + if (glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY) + return nullptr; + + if (glyph->bitmap.num_grays < 2) + return nullptr; // This should never happen + } PortabilityLayer::RenderedGlyphMetrics metrics; memset(&metrics, 0, sizeof(metrics)); @@ -141,7 +164,13 @@ GpFontRenderedGlyph_FreeType2 *GpFont_FreeType2::Render(uint32_t unicodeCodePoin metrics.m_advanceX = glyph->metrics.horiAdvance / 64; const size_t numRowsRequired = glyph->bitmap.rows; - size_t pitchRequired = (glyph->bitmap.width + 7) / 8; + size_t pitchRequired = 0; + + if (aa) + pitchRequired = (glyph->bitmap.width + 1) / 2; + else + pitchRequired = (glyph->bitmap.width + 7) / 8; + pitchRequired = pitchRequired + (GP_SYSTEM_MEMORY_ALIGNMENT - 1); pitchRequired -= pitchRequired % GP_SYSTEM_MEMORY_ALIGNMENT; @@ -158,8 +187,8 @@ GpFontRenderedGlyph_FreeType2 *GpFont_FreeType2::Render(uint32_t unicodeCodePoin unsigned int bmWidth = glyph->bitmap.width; unsigned int bmHeight = glyph->bitmap.rows; unsigned int bmPitch = glyph->bitmap.pitch; - unsigned int copyableBytesPerRow = (bmWidth + 7) / 8; const uint8_t *bmBytes = glyph->bitmap.buffer; + const uint16_t numGrays = glyph->bitmap.num_grays; size_t fillOffset = 0; for (unsigned int row = 0; row < bmHeight; row++) @@ -167,15 +196,36 @@ GpFontRenderedGlyph_FreeType2 *GpFont_FreeType2::Render(uint32_t unicodeCodePoin const uint8_t *bmReadStart = bmBytes + bmPitch * row; uint8_t *bmWriteStart = fillData + pitchRequired * row; - for (unsigned int i = 0; i < copyableBytesPerRow; i++) + if (aa) { - const uint8_t b = bmReadStart[i]; + for (size_t i = 0; i < pitchRequired; i++) + bmWriteStart[i] = 0; - uint8_t fillByte = 0; - for (int bit = 0; bit < 8; bit++) - fillByte |= ((b >> (7 - bit)) & 1) << bit; + for (size_t i = 0; i < bmWidth; i++) + { + const uint8_t b = bmReadStart[i]; + const uint8_t normalizedGray = (b * 30 + (numGrays - 1)) / ((numGrays - 1) * 2); - bmWriteStart[i] = fillByte; + if (i & 1) + bmWriteStart[i / 2] |= (normalizedGray << 4); + else + bmWriteStart[i / 2] = normalizedGray; + } + } + else + { + const size_t copyableBytesPerRow = (glyph->bitmap.width + 7) / 8; + + for (size_t i = 0; i < copyableBytesPerRow; i++) + { + const uint8_t b = bmReadStart[i]; + + uint8_t fillByte = 0; + for (int bit = 0; bit < 8; bit++) + fillByte |= ((b >> (7 - bit)) & 1) << bit; + + bmWriteStart[i] = fillByte; + } } } diff --git a/GpApp/Banner.cpp b/GpApp/Banner.cpp index 9585dfa..527e4c5 100644 --- a/GpApp/Banner.cpp +++ b/GpApp/Banner.cpp @@ -122,7 +122,7 @@ void DrawBannerMessage (Point topLeft) do { GetLineOfText(bannerStr, count, subStr); - workSrcMap->DrawString(Point::Create(topLeft.h + 16, topLeft.v + 32 + (count * 20)), subStr); + workSrcMap->DrawString(Point::Create(topLeft.h + 16, topLeft.v + 32 + (count * 20)), subStr, true); count++; } while (subStr[0] > 0); @@ -144,10 +144,10 @@ void DrawBannerMessage (Point topLeft) PasStringConcat(bannerStr, subStr); workSrcMap->SetForeColor(StdColors::Red()); - workSrcMap->DrawString(Point::Create(topLeft.h + 16, topLeft.v + 164), bannerStr); + workSrcMap->DrawString(Point::Create(topLeft.h + 16, topLeft.v + 164), bannerStr, true); GetLocalizedString(5, subStr); - workSrcMap->DrawString(Point::Create(topLeft.h + 16, topLeft.v + 180), subStr); + workSrcMap->DrawString(Point::Create(topLeft.h + 16, topLeft.v + 180), subStr, true); } workSrcMap->SetForeColor(StdColors::Black()); diff --git a/GpApp/ColorUtils.cpp b/GpApp/ColorUtils.cpp index 914d54c..cb96f6d 100644 --- a/GpApp/ColorUtils.cpp +++ b/GpApp/ColorUtils.cpp @@ -25,7 +25,7 @@ void ColorText (DrawSurface *surface, const Point &point, StringPtr theStr, long const PortabilityLayer::RGBAColor wasColor = surface->GetForeColor(); surface->SetForeColor(rgbaColor); - surface->DrawString(point, theStr); + surface->DrawString(point, theStr, true); surface->SetForeColor(wasColor); } diff --git a/GpApp/Coordinates.cpp b/GpApp/Coordinates.cpp index 63e50c2..898ddee 100644 --- a/GpApp/Coordinates.cpp +++ b/GpApp/Coordinates.cpp @@ -86,7 +86,7 @@ void UpdateCoordWindow (void) else PasStringConcat(tempStr, PSTR("-")); - surface->DrawString(Point::Create(5, 12), tempStr); + surface->DrawString(Point::Create(5, 12), tempStr, true); PasStringCopy(PSTR("v: "), tempStr); if (coordV != -1) @@ -97,7 +97,7 @@ void UpdateCoordWindow (void) else PasStringConcat(tempStr, PSTR("-")); - surface->DrawString(Point::Create(4, 22), tempStr); + surface->DrawString(Point::Create(4, 22), tempStr, true); surface->SetForeColor(StdColors::Blue()); PasStringCopy(PSTR("d: "), tempStr); @@ -109,7 +109,7 @@ void UpdateCoordWindow (void) else PasStringConcat(tempStr, PSTR("-")); - surface->DrawString(Point::Create(5, 32), tempStr); + surface->DrawString(Point::Create(5, 32), tempStr, true); surface->SetForeColor(StdColors::Black()); #endif } diff --git a/GpApp/DialogUtils.cpp b/GpApp/DialogUtils.cpp index e7cd69b..6937f64 100644 --- a/GpApp/DialogUtils.cpp +++ b/GpApp/DialogUtils.cpp @@ -640,7 +640,7 @@ void DrawDialogUserText (Dialog *dial, short item, StringPtr text, Boolean inver const int32_t ascender = surface->MeasureFontAscender(); const Point centeredDrawPoint = Point::Create((iRect.left + iRect.right - strWidth) / 2, (iRect.top + iRect.bottom + ascender) / 2); - surface->DrawString(centeredDrawPoint, stringCopy); + surface->DrawString(centeredDrawPoint, stringCopy, true); if (invert) { @@ -670,7 +670,7 @@ void DrawDialogUserText2 (Dialog *dial, short item, StringPtr text) CollapseStringToWidth(surface, stringCopy, iRect.right - iRect.left - 2); surface->SetForeColor(StdColors::Black()); - surface->DrawString(Point::Create(iRect.left, iRect.bottom), stringCopy); + surface->DrawString(Point::Create(iRect.left, iRect.bottom), stringCopy, true); } //-------------------------------------------------------------- LoadDialogPICT diff --git a/GpApp/GameOver.cpp b/GpApp/GameOver.cpp index 38c6676..a0e65cb 100644 --- a/GpApp/GameOver.cpp +++ b/GpApp/GameOver.cpp @@ -110,11 +110,11 @@ void SetUpFinalScreen (void) surface->SetForeColor(PortabilityLayer::RGBAColor::Create(0, 0, 0, 255)); const Point textShadowPos = Point::Create(offset + 1, textDown + 33 + (count * 20)); - surface->DrawString(textShadowPos, subStr); + surface->DrawString(textShadowPos, subStr, true); surface->SetForeColor(PortabilityLayer::RGBAColor::Create(255, 255, 255, 255)); const Point textPos = Point::Create(offset, textDown + 32 + (count * 20)); - surface->DrawString(textPos, subStr); + surface->DrawString(textPos, subStr, true); count++; } while (subStr[0] > 0); diff --git a/GpApp/GliderDefines.h b/GpApp/GliderDefines.h index c389e76..ce5ff9e 100644 --- a/GpApp/GliderDefines.h +++ b/GpApp/GliderDefines.h @@ -13,7 +13,7 @@ //#define CAREFULDEBUG #define COMPILENOCP #define COMPILEQT -#define BUILD_ARCADE_VERSION 1 +#define BUILD_ARCADE_VERSION 0 #define kYellowUnaccounted 1 #define kYellowFailedResOpen 2 diff --git a/GpApp/HighScores.cpp b/GpApp/HighScores.cpp index 785f748..df3209d 100644 --- a/GpApp/HighScores.cpp +++ b/GpApp/HighScores.cpp @@ -143,11 +143,11 @@ void DrawHighScores (DrawSurface *surface) const Point scoreShadowPoint = Point::Create(scoreLeft + ((kScoreWide - surface->MeasureString(tempStr)) / 2) - 1, dropIt - 66); surface->SetForeColor(blackColor); - surface->DrawString(scoreShadowPoint, tempStr); + surface->DrawString(scoreShadowPoint, tempStr, true); const Point scoreTextPoint = Point::Create(scoreLeft + ((kScoreWide - surface->MeasureString(tempStr)) / 2), dropIt - 65); surface->SetForeColor(cyanColor); - surface->DrawString(scoreTextPoint, tempStr); + surface->DrawString(scoreTextPoint, tempStr, true); surface->SetApplicationFont(12, PortabilityLayer::FontFamilyFlag_Bold); @@ -157,11 +157,11 @@ void DrawHighScores (DrawSurface *surface) bannerWidth = surface->MeasureString(tempStr); surface->SetForeColor(blackColor); const Point topScoreShadowPoint = Point::Create(scoreLeft + (kScoreWide - bannerWidth) / 2, dropIt - kKimsLifted); - surface->DrawString(topScoreShadowPoint, tempStr); + surface->DrawString(topScoreShadowPoint, tempStr, true); surface->SetForeColor(yellowColor); const Point topScoreTextPoint = Point::Create(scoreLeft + (kScoreWide - bannerWidth) / 2, dropIt - kKimsLifted - 1); - surface->DrawString(topScoreTextPoint, tempStr); + surface->DrawString(topScoreTextPoint, tempStr, true); QSetRect(&tempRect, 0, 0, bannerWidth + 8, kScoreSpacing); QOffsetRect(&tempRect, scoreLeft - 3 + (kScoreWide - bannerWidth) / 2, @@ -186,7 +186,7 @@ void DrawHighScores (DrawSurface *surface) strPos = Point::Create(scoreLeft + 1, dropIt - kScoreSpacing - kKimsLifted); else strPos = Point::Create(scoreLeft + 1, dropIt + (i * kScoreSpacing)); - surface->DrawString(strPos, tempStr); + surface->DrawString(strPos, tempStr, true); if (i == lastHighScore) surface->SetForeColor(whiteColor); else @@ -195,7 +195,7 @@ void DrawHighScores (DrawSurface *surface) strPos = Point::Create(scoreLeft + 0, dropIt - 1 - kScoreSpacing - kKimsLifted); else strPos = Point::Create(scoreLeft + 0, dropIt - 1 + (i * kScoreSpacing)); - surface->DrawString(strPos, tempStr); + surface->DrawString(strPos, tempStr, true); // draw high score name PasStringCopy(thisHousePtr->highScores.names[i], tempStr); surface->SetForeColor(blackColor); @@ -203,7 +203,7 @@ void DrawHighScores (DrawSurface *surface) strPos = Point::Create(scoreLeft + 31, dropIt - kScoreSpacing - kKimsLifted); else strPos = Point::Create(scoreLeft + 31, dropIt + (i * kScoreSpacing)); - surface->DrawString(strPos, tempStr); + surface->DrawString(strPos, tempStr, true); if (i == lastHighScore) surface->SetForeColor(whiteColor); else @@ -212,7 +212,7 @@ void DrawHighScores (DrawSurface *surface) strPos = Point::Create(scoreLeft + 30, dropIt - 1 - kScoreSpacing - kKimsLifted); else strPos = Point::Create(scoreLeft + 30, dropIt - 1 + (i * kScoreSpacing)); - surface->DrawString(strPos, tempStr); + surface->DrawString(strPos, tempStr, true); // draw level number NumToString(thisHousePtr->highScores.levels[i], tempStr); surface->SetForeColor(blackColor); @@ -220,7 +220,7 @@ void DrawHighScores (DrawSurface *surface) strPos = Point::Create(scoreLeft + 161, dropIt - kScoreSpacing - kKimsLifted); else strPos = Point::Create(scoreLeft + 161, dropIt + (i * kScoreSpacing)); - surface->DrawString(strPos, tempStr); + surface->DrawString(strPos, tempStr, true); if (i == lastHighScore) surface->SetForeColor(whiteColor); else @@ -229,7 +229,7 @@ void DrawHighScores (DrawSurface *surface) strPos = Point::Create(scoreLeft + 160, dropIt - 1 - kScoreSpacing - kKimsLifted); else strPos = Point::Create(scoreLeft + 160, dropIt - 1 + (i * kScoreSpacing)); - surface->DrawString(strPos, tempStr); + surface->DrawString(strPos, tempStr, true); // draw word "rooms" if (thisHousePtr->highScores.levels[i] == 1) GetLocalizedString(6, tempStr); @@ -240,13 +240,13 @@ void DrawHighScores (DrawSurface *surface) strPos = Point::Create(scoreLeft + 193, dropIt - kScoreSpacing - kKimsLifted); else strPos = Point::Create(scoreLeft + 193, dropIt + (i * kScoreSpacing)); - surface->DrawString(strPos, tempStr); + surface->DrawString(strPos, tempStr, true); surface->SetForeColor(cyanColor); if (i == 0) strPos = Point::Create(scoreLeft + 192, dropIt - 1 - kScoreSpacing - kKimsLifted); else strPos = Point::Create(scoreLeft + 192, dropIt - 1 + (i * kScoreSpacing)); - surface->DrawString(strPos, tempStr); + surface->DrawString(strPos, tempStr, true); // draw high score points NumToString(thisHousePtr->highScores.scores[i], tempStr); surface->SetForeColor(blackColor); @@ -254,7 +254,7 @@ void DrawHighScores (DrawSurface *surface) strPos = Point::Create(scoreLeft + 291, dropIt - kScoreSpacing - kKimsLifted); else strPos = Point::Create(scoreLeft + 291, dropIt + (i * kScoreSpacing)); - surface->DrawString(strPos, tempStr); + surface->DrawString(strPos, tempStr, true); if (i == lastHighScore) surface->SetForeColor(whiteColor); else @@ -263,7 +263,7 @@ void DrawHighScores (DrawSurface *surface) strPos = Point::Create(scoreLeft + 290, dropIt - 1 - kScoreSpacing - kKimsLifted); else strPos = Point::Create(scoreLeft + 290, dropIt - 1 + (i * kScoreSpacing)); - surface->DrawString(strPos, tempStr); + surface->DrawString(strPos, tempStr, true); } } @@ -273,7 +273,7 @@ void DrawHighScores (DrawSurface *surface) const Point textPos = Point::Create(scoreLeft + 80, dropIt - 1 + (10 * kScoreSpacing)); GetLocalizedString(8, tempStr); - surface->DrawString(textPos, tempStr); + surface->DrawString(textPos, tempStr, true); surface->SetForeColor(blackColor); } diff --git a/GpApp/Input.cpp b/GpApp/Input.cpp index 9fb117e..a358cc6 100644 --- a/GpApp/Input.cpp +++ b/GpApp/Input.cpp @@ -220,7 +220,7 @@ void DoHeliumEngaged (gliderPtr thisGlider) #else - if (theKeys->IsSet(kCommandKeyMap)) + if (theKeys->IsSet(PL_KEY_EITHER_SPECIAL(kControl))) DoCommandKey(); #endif diff --git a/GpApp/MainWindow.cpp b/GpApp/MainWindow.cpp index a18fdaa..5f764e0 100644 --- a/GpApp/MainWindow.cpp +++ b/GpApp/MainWindow.cpp @@ -74,7 +74,7 @@ void DrawOnSplash(DrawSurface *surface) if (thisMac.isDepth == 4) { surface->SetForeColor(PortabilityLayer::RGBAColor::Create(255, 255, 255, 255)); - surface->DrawString(textPoint, houseLoadedStr); + surface->DrawString(textPoint, houseLoadedStr, true); } else { diff --git a/GpApp/Music.cpp b/GpApp/Music.cpp index a5765bc..e9be75c 100644 --- a/GpApp/Music.cpp +++ b/GpApp/Music.cpp @@ -29,6 +29,8 @@ PLError_t DumpMusicSounds (void); PLError_t OpenMusicChannel (void); PLError_t CloseMusicChannel (void); +THandle ParseAndConvertSound(const THandle &handle); + PortabilityLayer::AudioChannel *musicChannel; Ptr theMusicData[kMaxMusic]; @@ -210,17 +212,17 @@ PLError_t LoadMusicSounds (void) for (i = 0; i < kMaxMusic; i++) { - theSound = GetResource('snd ', i + kBaseBufferMusicID); + theSound = ParseAndConvertSound(GetResource('snd ', i + kBaseBufferMusicID)); if (theSound == nil) return PLErrors::kOutOfMemory; - soundDataSize = GetHandleSize(theSound) - 20L; + soundDataSize = GetHandleSize(theSound); theMusicData[i] = PortabilityLayer::MemoryManager::GetInstance()->Alloc(soundDataSize); if (theMusicData[i] == nil) return PLErrors::kOutOfMemory; - BlockMove((Ptr)(static_cast(*theSound) + 20L), theMusicData[i], soundDataSize); + BlockMove(static_cast(*theSound), theMusicData[i], soundDataSize); theSound.Dispose(); } return (theErr); diff --git a/GpApp/Room.cpp b/GpApp/Room.cpp index 7d59c16..02b4194 100644 --- a/GpApp/Room.cpp +++ b/GpApp/Room.cpp @@ -250,9 +250,9 @@ void ReadyBackground (short theID, short *theTiles) const Point textPoint = Point::Create(10, 20); if (houseUnlocked) - workSrcMap->DrawString(textPoint, PSTR("No rooms")); + workSrcMap->DrawString(textPoint, PSTR("No rooms"), true); else - workSrcMap->DrawString(textPoint, PSTR("Nothing to show")); + workSrcMap->DrawString(textPoint, PSTR("Nothing to show"), true); CopyBits((BitMap *)*GetGWorldPixMap(workSrcMap), (BitMap *)*GetGWorldPixMap(backSrcMap), diff --git a/GpApp/Scoreboard.cpp b/GpApp/Scoreboard.cpp index 91da734..d104ac1 100644 --- a/GpApp/Scoreboard.cpp +++ b/GpApp/Scoreboard.cpp @@ -167,15 +167,15 @@ void RefreshRoomTitle (short mode) switch (mode) { case kEscapedTitleMode: - surface->DrawString(strShadowPoint, PSTR("Hit Delete key if unable to Follow")); + surface->DrawString(strShadowPoint, PSTR("Hit Delete key if unable to Follow"), true); break; case kSavingTitleMode: - surface->DrawString(strShadowPoint, PSTR("Saving GameÉ")); + surface->DrawString(strShadowPoint, PSTR("Saving GameÉ"), true); break; default: - surface->DrawString(strShadowPoint, thisRoom->name); + surface->DrawString(strShadowPoint, thisRoom->name, true); break; } @@ -184,15 +184,15 @@ void RefreshRoomTitle (short mode) switch (mode) { case kEscapedTitleMode: - surface->DrawString(strPoint, PSTR("Hit Delete key if unable to Follow")); + surface->DrawString(strPoint, PSTR("Hit Delete key if unable to Follow"), true); break; case kSavingTitleMode: - surface->DrawString(strPoint, PSTR("Saving GameÉ")); + surface->DrawString(strPoint, PSTR("Saving GameÉ"), true); break; default: - surface->DrawString(strPoint, thisRoom->name); + surface->DrawString(strPoint, thisRoom->name, true); break; } @@ -225,10 +225,10 @@ void RefreshNumGliders (void) const Point textPoint = Point::Create(0, 9); surface->SetForeColor(PortabilityLayer::RGBAColor::Create(0, 0, 0, 255)); - surface->DrawString(shadowPoint, nGlidersStr); + surface->DrawString(shadowPoint, nGlidersStr, true); surface->SetForeColor(PortabilityLayer::RGBAColor::Create(255, 255, 255, 255)); - surface->DrawString(textPoint, nGlidersStr); + surface->DrawString(textPoint, nGlidersStr, true); CopyBits((BitMap *)*GetGWorldPixMap(boardGSrcMap), (BitMap *)*GetGWorldPixMap(boardSrcMap), @@ -254,10 +254,10 @@ void RefreshPoints (void) const Point textPoint = Point::Create(0, 9); surface->SetForeColor(PortabilityLayer::RGBAColor::Create(0, 0, 0, 255)); - surface->DrawString(shadowPoint, scoreStr); + surface->DrawString(shadowPoint, scoreStr, true); surface->SetForeColor(PortabilityLayer::RGBAColor::Create(255, 255, 255, 255)); - surface->DrawString(textPoint, scoreStr); + surface->DrawString(textPoint, scoreStr, true); CopyBits((BitMap *)*GetGWorldPixMap(boardPSrcMap), (BitMap *)*GetGWorldPixMap(boardSrcMap), @@ -285,10 +285,10 @@ void QuickGlidersRefresh (void) const Point textPoint = Point::Create(0, 9); surface->SetForeColor(PortabilityLayer::RGBAColor::Create(0, 0, 0, 255)); - surface->DrawString(shadowPoint, nGlidersStr); + surface->DrawString(shadowPoint, nGlidersStr, true); surface->SetForeColor(PortabilityLayer::RGBAColor::Create(255, 255, 255, 255)); - surface->DrawString(textPoint, nGlidersStr); + surface->DrawString(textPoint, nGlidersStr, true); CopyBits((BitMap *)*GetGWorldPixMap(boardGSrcMap), GetPortBitMapForCopyBits(GetWindowPort(boardWindow)), @@ -315,10 +315,10 @@ void QuickScoreRefresh (void) const Point textPoint = Point::Create(0, 9); surface->SetForeColor(PortabilityLayer::RGBAColor::Create(0, 0, 0, 255)); - surface->DrawString(shadowPoint, scoreStr); + surface->DrawString(shadowPoint, scoreStr, true); surface->SetForeColor(PortabilityLayer::RGBAColor::Create(255, 255, 255, 255)); - surface->DrawString(textPoint, scoreStr); + surface->DrawString(textPoint, scoreStr, true); CopyBits((BitMap *)*GetGWorldPixMap(boardPSrcMap), GetPortBitMapForCopyBits(GetWindowPort(boardWindow)), diff --git a/GpApp/Sound.cpp b/GpApp/Sound.cpp index fa98644..e231983 100644 --- a/GpApp/Sound.cpp +++ b/GpApp/Sound.cpp @@ -12,6 +12,7 @@ #include "MemoryManager.h" #include "SoundSync.h" #include "VirtualDirectory.h" +#include "WaveFormat.h" #define kBaseBufferSoundID 1000 @@ -25,7 +26,7 @@ PLError_t LoadBufferSounds (void); void DumpBufferSounds (void); PLError_t OpenSoundChannels (void); void CloseSoundChannels (void); - +THandle ParseAndConvertSound(const THandle &handle); PortabilityLayer::AudioChannel *channel0, *channel1, *channel2; Ptr theSoundData[kMaxSounds]; @@ -167,6 +168,9 @@ void PlayExclusiveSoundChannel(short channelIndex, short soundID, short oldPrior } } +//-------------------------------------------------------------- ParseAndConvertSound + + //-------------------------------------------------------------- LoadTriggerSound PLError_t LoadTriggerSound (short soundID) @@ -183,14 +187,14 @@ PLError_t LoadTriggerSound (short soundID) theErr = PLErrors::kNone; - theSound = GetResource('snd ', soundID); + theSound = ParseAndConvertSound(GetResource('snd ', soundID)); if (theSound == nil) { theErr = PLErrors::kFileNotFound; } else { - soundDataSize = GetHandleSize(theSound) - 20L; + soundDataSize = GetHandleSize(theSound); theSoundData[kMaxSounds - 1] = PortabilityLayer::MemoryManager::GetInstance()->Alloc(soundDataSize); if (theSoundData[kMaxSounds - 1] == nil) { @@ -199,7 +203,7 @@ PLError_t LoadTriggerSound (short soundID) } else { - BlockMove((Ptr)((Byte*)(*theSound) + 20L), theSoundData[kMaxSounds - 1], soundDataSize); + BlockMove((Byte*)(*theSound), theSoundData[kMaxSounds - 1], soundDataSize); theSound.Dispose(); } } @@ -230,17 +234,17 @@ PLError_t LoadBufferSounds (void) for (i = 0; i < kMaxSounds - 1; i++) { - theSound = GetResource('snd ', i + kBaseBufferSoundID); + theSound = ParseAndConvertSound(GetResource('snd ', i + kBaseBufferSoundID)); if (theSound == nil) return (PLErrors::kOutOfMemory); - soundDataSize = GetHandleSize(theSound) - 20L; + soundDataSize = GetHandleSize(theSound); theSoundData[i] = PortabilityLayer::MemoryManager::GetInstance()->Alloc(soundDataSize); if (theSoundData[i] == nil) return (PLErrors::kOutOfMemory); - BlockMove((Ptr)((Byte*)(*theSound) + 20L), theSoundData[i], soundDataSize); + BlockMove(*theSound, theSoundData[i], soundDataSize); theSound.Dispose(); } @@ -408,3 +412,143 @@ void BitchAboutSM3 (void) hitWhat = Alert(kNoSoundManager3Alert, nil); } + + +//-------------------------------------------------------------- ParseAndConvertSound + +THandle ParseAndConvertSoundChecked(const THandle &handle) +{ + const uint8_t *dataStart = static_cast(*handle); + const size_t size = handle.MMBlock()->m_size; + + if (size < sizeof(PortabilityLayer::RIFFTag)) + return THandle(); + + PortabilityLayer::RIFFTag mainRiffTag; + memcpy(&mainRiffTag, dataStart, sizeof(PortabilityLayer::RIFFTag)); + + if (mainRiffTag.m_tag != PortabilityLayer::WaveConstants::kRiffChunkID) + return THandle(); + + const uint32_t riffSize = mainRiffTag.m_chunkSize; + if (riffSize < 4 || riffSize - 4 > size - sizeof(PortabilityLayer::RIFFTag)) + return THandle(); + + const uint8_t *riffStart = dataStart + sizeof(PortabilityLayer::RIFFTag); + const uint8_t *riffEnd = riffStart + riffSize; + + const uint8_t *formatTagLoc = nullptr; + const uint8_t *dataTagLoc = nullptr; + + LEUInt32_t waveMarker; + memcpy(&waveMarker, riffStart, 4); + + if (waveMarker != PortabilityLayer::WaveConstants::kWaveChunkID) + return THandle(); + + const uint8_t *tagSearchLoc = riffStart + 4; + + // Find tags + while (tagSearchLoc != riffEnd) + { + if (riffEnd - tagSearchLoc < sizeof(PortabilityLayer::RIFFTag)) + return THandle(); + + PortabilityLayer::RIFFTag riffTag; + memcpy(&riffTag, tagSearchLoc, sizeof(PortabilityLayer::RIFFTag)); + + if (riffTag.m_tag == PortabilityLayer::WaveConstants::kFormatChunkID) + formatTagLoc = tagSearchLoc; + else if (riffTag.m_tag == PortabilityLayer::WaveConstants::kDataChunkID) + dataTagLoc = tagSearchLoc; + + const uint32_t riffTagSizeUnpadded = riffTag.m_chunkSize; + + if (riffTagSizeUnpadded == 0xffffffffU) + return THandle(); + + const uint32_t riffTagSizePadded = riffTagSizeUnpadded + (riffTagSizeUnpadded & 1); + + tagSearchLoc += sizeof(PortabilityLayer::RIFFTag); + + if (riffEnd - tagSearchLoc < riffTagSizePadded) + return THandle(); + + tagSearchLoc += riffTagSizePadded; + } + + if (formatTagLoc == nullptr || dataTagLoc == nullptr) + return THandle(); + + PortabilityLayer::RIFFTag fmtTag; + memcpy(&fmtTag, formatTagLoc, sizeof(PortabilityLayer::RIFFTag)); + + const uint8_t *formatContents = formatTagLoc + sizeof(PortabilityLayer::RIFFTag); + + PortabilityLayer::RIFFTag dataTag; + memcpy(&dataTag, dataTagLoc, sizeof(PortabilityLayer::RIFFTag)); + + const uint8_t *dataContents = dataTagLoc + sizeof(PortabilityLayer::RIFFTag); + + PortabilityLayer::WaveFormatChunkV3 formatChunkV3; + + memset(&formatChunkV3, 0, sizeof(formatChunkV3)); + + int formatChunkVersion = 0; + size_t copyableSize = 0; + if (fmtTag.m_chunkSize >= sizeof(PortabilityLayer::WaveFormatChunkV3)) + { + formatChunkVersion = 3; + copyableSize = sizeof(PortabilityLayer::WaveFormatChunkV3); + } + else if (fmtTag.m_chunkSize >= sizeof(PortabilityLayer::WaveFormatChunkV2)) + { + formatChunkVersion = 2; + copyableSize = sizeof(PortabilityLayer::WaveFormatChunkV2); + } + else if (fmtTag.m_chunkSize >= sizeof(PortabilityLayer::WaveFormatChunkV1)) + { + formatChunkVersion = 1; + copyableSize = sizeof(PortabilityLayer::WaveFormatChunkV1); + } + else + return THandle(); + + memcpy(&formatChunkV3, formatContents, copyableSize); + + const PortabilityLayer::WaveFormatChunkV2 formatChunkV2 = formatChunkV3.m_v2; + const PortabilityLayer::WaveFormatChunkV1 formatChunkV1 = formatChunkV2.m_v1; + + if (formatChunkV1.m_bitsPerSample != 8) + return THandle(); + + if (formatChunkV1.m_formatCode != PortabilityLayer::WaveConstants::kFormatPCM || + formatChunkV1.m_numChannels != 1 || + formatChunkV1.m_blockAlignmentBytes != 1 || + formatChunkV1.m_bitsPerSample != 8) + return THandle(); + + THandle convertedHandle = THandle(PortabilityLayer::MemoryManager::GetInstance()->AllocHandle(4 + dataTag.m_chunkSize)); + if (!convertedHandle) + return THandle(); + + uint8_t *handleData = static_cast(*convertedHandle); + + uint32_t dataSize = dataTag.m_chunkSize; + memcpy(handleData, &dataSize, 4); + + memcpy(handleData + 4, dataContents, dataSize); + + return convertedHandle; +} + +THandle ParseAndConvertSound(const THandle &handle) +{ + if (!handle) + return THandle(); + + THandle converted = ParseAndConvertSoundChecked(handle); + handle.Dispose(); + + return converted; +} diff --git a/GpApp/WindowUtils.cpp b/GpApp/WindowUtils.cpp index 64df0ad..5de63b0 100644 --- a/GpApp/WindowUtils.cpp +++ b/GpApp/WindowUtils.cpp @@ -145,7 +145,7 @@ void SetMessageWindowMessage (StringPtr message) const Point textPoint = Point::Create(mssgWindowRect.left, mssgWindowRect.bottom - 6); surface->SetForeColor(StdColors::Black()); - surface->DrawString(textPoint, message); + surface->DrawString(textPoint, message, true); } } diff --git a/PortabilityLayer/AntiAliasTable.cpp b/PortabilityLayer/AntiAliasTable.cpp new file mode 100644 index 0000000..62aa0dd --- /dev/null +++ b/PortabilityLayer/AntiAliasTable.cpp @@ -0,0 +1,56 @@ +#include "AntiAliasTable.h" +#include "RGBAColor.h" + +// TODO: This is not gamma correct... do we care? +namespace PortabilityLayer +{ + void AntiAliasTable::GenerateForPalette(const RGBAColor &baseColorRef, const RGBAColor *colors, size_t numColors) + { + const RGBAColor baseColor = baseColorRef; + + if (numColors > 256) + numColors = 256; + + unsigned int baseCh[3] = { baseColor.r, baseColor.g, baseColor.b }; + + for (size_t i = 0; i < numColors; i++) + { + const RGBAColor existingColor = colors[i]; + + unsigned int existingCh[3] = { existingColor.r, existingColor.g, existingColor.b }; + + // 0 alpha is always the same color + m_aaTranslate[i][0] = static_cast(i); + + for (unsigned int b = 1; b < 16; b++) + { + unsigned int newCh[3]; + + for (unsigned int ch = 0; ch < 3; ch++) + newCh[ch] = (15 - b) * existingCh[ch] + b * baseCh[ch]; + + uint32_t bestError = 0xffffffffU; + size_t bestColor = 0; + for (size_t cmp = 0; cmp < numColors; cmp++) + { + int16_t existingChScaled[3] = { colors[cmp].r * 15, colors[cmp].g * 15, colors[cmp].b * 15 }; + + uint32_t error = 0; + for (unsigned int ch = 0; ch < 3; ch++) + { + int16_t delta = static_cast(newCh[ch]) - existingChScaled[ch]; + error += static_cast(delta * delta); + } + + if (error < bestError) + { + bestError = error; + bestColor = cmp; + } + } + + m_aaTranslate[i][b] = static_cast(bestColor); + } + } + } +} diff --git a/PortabilityLayer/AntiAliasTable.h b/PortabilityLayer/AntiAliasTable.h new file mode 100644 index 0000000..13f4e5d --- /dev/null +++ b/PortabilityLayer/AntiAliasTable.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +namespace PortabilityLayer +{ + struct RGBAColor; + + struct AntiAliasTable + { + // Striped 256x16 because constant background color is more likely than constant sample + uint8_t m_aaTranslate[256][16]; + + void GenerateForPalette(const RGBAColor &baseColor, const RGBAColor *colors, size_t numColors); + }; +} diff --git a/PortabilityLayer/FontManager.cpp b/PortabilityLayer/FontManager.cpp index a42b691..ac2b3c9 100644 --- a/PortabilityLayer/FontManager.cpp +++ b/PortabilityLayer/FontManager.cpp @@ -24,8 +24,8 @@ namespace PortabilityLayer FontFamily *GetSystemFont(int textSize, int variationFlags) const override; FontFamily *GetApplicationFont(int textSize, int variationFlags) const override; - RenderedFont *GetRenderedFont(HostFont *font, int size, FontHacks fontHacks) override; - RenderedFont *GetRenderedFontFromFamily(FontFamily *font, int size, int flags) override; + RenderedFont *GetRenderedFont(HostFont *font, int size, bool aa, FontHacks fontHacks) override; + RenderedFont *GetRenderedFontFromFamily(FontFamily *font, int size, bool aa, int flags) override; static FontManagerImpl *GetInstance(); @@ -38,6 +38,7 @@ namespace PortabilityLayer const HostFont *m_font; int m_size; uint32_t m_lastUsage; + bool m_aa; }; FontManagerImpl(); @@ -109,7 +110,7 @@ namespace PortabilityLayer return m_applicationFont; } - RenderedFont *FontManagerImpl::GetRenderedFont(HostFont *font, int size, FontHacks fontHacks) + RenderedFont *FontManagerImpl::GetRenderedFont(HostFont *font, int size, bool aa, FontHacks fontHacks) { CachedRenderedFont *newCacheSlot = &m_cachedRenderedFonts[0]; @@ -122,7 +123,7 @@ namespace PortabilityLayer break; } - if (crf.m_font == font && crf.m_size == size) + if (crf.m_font == font && crf.m_size == size && crf.m_aa == aa) { crf.m_lastUsage = m_usageCounter; RenderedFont *rf = crf.m_rfont; @@ -138,7 +139,7 @@ namespace PortabilityLayer newCacheSlot = &crf; } - RenderedFont *rfont = FontRenderer::GetInstance()->RenderFont(font, size, fontHacks); + RenderedFont *rfont = FontRenderer::GetInstance()->RenderFont(font, size, aa, fontHacks); if (!rfont) return nullptr; @@ -149,6 +150,7 @@ namespace PortabilityLayer newCacheSlot->m_lastUsage = m_usageCounter; newCacheSlot->m_size = size; newCacheSlot->m_rfont = rfont; + newCacheSlot->m_aa = aa; if (m_usageCounter == UINT32_MAX) ResetUsageCounter(); @@ -158,7 +160,7 @@ namespace PortabilityLayer return rfont; } - RenderedFont *FontManagerImpl::GetRenderedFontFromFamily(FontFamily *fontFamily, int size, int flags) + RenderedFont *FontManagerImpl::GetRenderedFontFromFamily(FontFamily *fontFamily, int size, bool aa, int flags) { const int variation = fontFamily->GetVariationForFlags(flags); @@ -166,7 +168,7 @@ namespace PortabilityLayer if (!hostFont) return nullptr; - return PortabilityLayer::FontManager::GetInstance()->GetRenderedFont(hostFont, size, fontFamily->GetHacksForVariation(variation)); + return PortabilityLayer::FontManager::GetInstance()->GetRenderedFont(hostFont, size, aa, fontFamily->GetHacksForVariation(variation)); } FontManagerImpl *FontManagerImpl::GetInstance() diff --git a/PortabilityLayer/FontManager.h b/PortabilityLayer/FontManager.h index 2a39c6e..4d0c648 100644 --- a/PortabilityLayer/FontManager.h +++ b/PortabilityLayer/FontManager.h @@ -17,8 +17,8 @@ namespace PortabilityLayer virtual FontFamily *GetSystemFont(int fontSize, int variationFlags) const = 0; virtual FontFamily *GetApplicationFont(int fontSize, int variationFlags) const = 0; - virtual RenderedFont *GetRenderedFont(HostFont *font, int size, FontHacks fontHacks) = 0; - virtual RenderedFont *GetRenderedFontFromFamily(FontFamily *fontFamily, int fontSize, int flags) = 0; + virtual RenderedFont *GetRenderedFont(HostFont *font, int size, bool aa, FontHacks fontHacks) = 0; + virtual RenderedFont *GetRenderedFontFromFamily(FontFamily *fontFamily, int fontSize, bool aa, int flags) = 0; static FontManager *GetInstance(); }; diff --git a/PortabilityLayer/FontRenderer.cpp b/PortabilityLayer/FontRenderer.cpp index 5d360bd..6899941 100644 --- a/PortabilityLayer/FontRenderer.cpp +++ b/PortabilityLayer/FontRenderer.cpp @@ -23,22 +23,24 @@ namespace PortabilityLayer bool GetGlyph(unsigned int character, const RenderedGlyphMetrics *&outMetricsPtr, const void *&outData) const override; const RenderedFontMetrics &GetMetrics() const override; size_t MeasureString(const uint8_t *chars, size_t len) const override; + bool IsAntiAliased() const override; void Destroy() override; void SetCharData(unsigned int charID, const void *data, size_t dataOffset, const RenderedGlyphMetrics &metrics); void SetFontMetrics(const RenderedFontMetrics &metrics); - static RenderedFontImpl *Create(size_t glyphDataSize); + static RenderedFontImpl *Create(size_t glyphDataSize, bool aa); private: - explicit RenderedFontImpl(void *data); + RenderedFontImpl(void *data, bool aa); ~RenderedFontImpl(); size_t m_dataOffsets[256]; RenderedGlyphMetrics m_glyphMetrics[256]; RenderedFontMetrics m_fontMetrics; + bool m_isAntiAliased; void *m_data; }; @@ -46,7 +48,7 @@ namespace PortabilityLayer class FontRendererImpl final : public FontRenderer { public: - RenderedFont *RenderFont(HostFont *font, int size, FontHacks fontHacks) override; + RenderedFont *RenderFont(HostFont *font, int size, bool aa, FontHacks fontHacks) override; static FontRendererImpl *GetInstance(); @@ -71,7 +73,6 @@ namespace PortabilityLayer return m_fontMetrics; } - size_t RenderedFontImpl::MeasureString(const uint8_t *chars, size_t len) const { size_t measure = 0; @@ -85,6 +86,11 @@ namespace PortabilityLayer return measure; } + bool RenderedFontImpl::IsAntiAliased() const + { + return m_isAntiAliased; + } + void RenderedFontImpl::Destroy() { this->~RenderedFontImpl(); @@ -103,7 +109,7 @@ namespace PortabilityLayer m_fontMetrics = metrics; } - RenderedFontImpl *RenderedFontImpl::Create(size_t glyphDataSize) + RenderedFontImpl *RenderedFontImpl::Create(size_t glyphDataSize, bool aa) { size_t alignedPrefixSize = sizeof(RenderedFontImpl) + GP_SYSTEM_MEMORY_ALIGNMENT - 1; alignedPrefixSize -= alignedPrefixSize % GP_SYSTEM_MEMORY_ALIGNMENT; @@ -119,11 +125,12 @@ namespace PortabilityLayer memset(storage, 0, allocSize); - return new (storage) RenderedFontImpl(static_cast(storage) + alignedPrefixSize); + return new (storage) RenderedFontImpl(static_cast(storage) + alignedPrefixSize, aa); } - RenderedFontImpl::RenderedFontImpl(void *data) + RenderedFontImpl::RenderedFontImpl(void *data, bool aa) : m_data(data) + , m_isAntiAliased(aa) { memset(m_glyphMetrics, 0, sizeof(m_glyphMetrics)); memset(&m_fontMetrics, 0, sizeof(m_fontMetrics)); @@ -134,7 +141,7 @@ namespace PortabilityLayer { } - RenderedFont *FontRendererImpl::RenderFont(HostFont *font, int size, FontHacks fontHacks) + RenderedFont *FontRendererImpl::RenderFont(HostFont *font, int size, bool aa, FontHacks fontHacks) { const unsigned int numCharacters = 256; @@ -156,7 +163,7 @@ namespace PortabilityLayer if (unicodeCodePoint == 0xffff) continue; - glyphs[i] = font->Render(unicodeCodePoint, size); + glyphs[i] = font->Render(unicodeCodePoint, size, aa); } size_t glyphDataSize = GP_SYSTEM_MEMORY_ALIGNMENT; // So we can use 0 to mean no data @@ -170,7 +177,7 @@ namespace PortabilityLayer } } - RenderedFontImpl *rfont = RenderedFontImpl::Create(glyphDataSize); + RenderedFontImpl *rfont = RenderedFontImpl::Create(glyphDataSize, aa); if (rfont) { size_t fillOffset = GP_SYSTEM_MEMORY_ALIGNMENT; @@ -185,7 +192,7 @@ namespace PortabilityLayer RenderedGlyphMetrics metrics = glyph->GetMetrics(); const void *data = glyph->GetData(); - if (fontHacks == FontHacks_Roboto) + if (fontHacks == FontHacks_Roboto && !aa) { if (size < 32) { diff --git a/PortabilityLayer/FontRenderer.h b/PortabilityLayer/FontRenderer.h index 18b0c60..9718262 100644 --- a/PortabilityLayer/FontRenderer.h +++ b/PortabilityLayer/FontRenderer.h @@ -10,7 +10,7 @@ namespace PortabilityLayer class FontRenderer { public: - virtual RenderedFont *RenderFont(HostFont *font, int size, FontHacks fontHacks) = 0; + virtual RenderedFont *RenderFont(HostFont *font, int size, bool aa, FontHacks fontHacks) = 0; static FontRenderer *GetInstance(); }; diff --git a/PortabilityLayer/HostFont.h b/PortabilityLayer/HostFont.h index 38d5253..596f292 100644 --- a/PortabilityLayer/HostFont.h +++ b/PortabilityLayer/HostFont.h @@ -11,7 +11,7 @@ namespace PortabilityLayer { public: virtual void Destroy() = 0; - virtual HostFontRenderedGlyph *Render(uint32_t unicodeCodePoint, unsigned int size) = 0; + virtual HostFontRenderedGlyph *Render(uint32_t unicodeCodePoint, unsigned int size, bool aa) = 0; virtual bool GetLineSpacing(unsigned int size, int32_t &outSpacing) = 0; }; } diff --git a/PortabilityLayer/MenuManager.cpp b/PortabilityLayer/MenuManager.cpp index 549313d..b6639a7 100644 --- a/PortabilityLayer/MenuManager.cpp +++ b/PortabilityLayer/MenuManager.cpp @@ -757,7 +757,7 @@ namespace PortabilityLayer if (menuHdl != selectedMenuHdl) { const Point itemPos = Point::Create(static_cast(xCoordinate), kMenuBarTextYOffset); - graf->DrawString(itemPos, PLPasStr(static_cast(menu->stringBlobHandle->m_contents))); + graf->DrawString(itemPos, PLPasStr(static_cast(menu->stringBlobHandle->m_contents)), true); } } } @@ -776,7 +776,7 @@ namespace PortabilityLayer size_t xCoordinate = menu->cumulativeOffset + (menu->menuIndex * 2) * kMenuBarItemPadding + kMenuBarInitialPadding; const Point itemPos = Point::Create(static_cast(xCoordinate), kMenuBarTextYOffset); - graf->DrawString(itemPos, PLPasStr(static_cast(menu->stringBlobHandle->m_contents))); + graf->DrawString(itemPos, PLPasStr(static_cast(menu->stringBlobHandle->m_contents)), true); } } @@ -835,7 +835,7 @@ namespace PortabilityLayer if (!fontFamily) return; - PortabilityLayer::RenderedFont *rfont = PortabilityLayer::FontManager::GetInstance()->GetRenderedFontFromFamily(fontFamily, kMenuFontSize, kMenuFontFlags); + PortabilityLayer::RenderedFont *rfont = PortabilityLayer::FontManager::GetInstance()->GetRenderedFontFromFamily(fontFamily, kMenuFontSize, true, kMenuFontFlags); if (!rfont) return; @@ -879,7 +879,7 @@ namespace PortabilityLayer if (!fontFamily) return; - PortabilityLayer::RenderedFont *rfont = PortabilityLayer::FontManager::GetInstance()->GetRenderedFontFromFamily(fontFamily, kMenuFontSize, kMenuFontFlags); + PortabilityLayer::RenderedFont *rfont = PortabilityLayer::FontManager::GetInstance()->GetRenderedFontFromFamily(fontFamily, kMenuFontSize, true, kMenuFontFlags); if (!rfont) return; @@ -1132,7 +1132,7 @@ namespace PortabilityLayer itemPos.v = item.layoutYOffset + kMenuItemTextYOffset; - surface->DrawString(itemPos, PLPasStr(strBlob + item.nameOffsetInStringBlob)); + surface->DrawString(itemPos, PLPasStr(strBlob + item.nameOffsetInStringBlob), true); } if (m_haveItem) @@ -1148,7 +1148,7 @@ namespace PortabilityLayer itemPos.v = item.layoutYOffset + kMenuItemTextYOffset; - surface->DrawString(itemPos, PLPasStr(strBlob + item.nameOffsetInStringBlob)); + surface->DrawString(itemPos, PLPasStr(strBlob + item.nameOffsetInStringBlob), true); } m_menuGraf->m_port.SetDirty(QDPortDirtyFlag_Contents); diff --git a/PortabilityLayer/PLButtonWidget.cpp b/PortabilityLayer/PLButtonWidget.cpp index f07c219..1c85f67 100644 --- a/PortabilityLayer/PLButtonWidget.cpp +++ b/PortabilityLayer/PLButtonWidget.cpp @@ -62,6 +62,6 @@ namespace PortabilityLayer surface->SetSystemFont(12, PortabilityLayer::FontFamilyFlag_Bold); int32_t x = (m_rect.left + m_rect.right - static_cast(surface->MeasureString(m_text.ToShortStr()))) / 2; int32_t y = (m_rect.top + m_rect.bottom + static_cast(surface->MeasureFontAscender())) / 2; - surface->DrawString(Point::Create(x, y), m_text.ToShortStr()); + surface->DrawString(Point::Create(x, y), m_text.ToShortStr(), true); } } diff --git a/PortabilityLayer/PLLabelWidget.cpp b/PortabilityLayer/PLLabelWidget.cpp index 4f2529b..73ba867 100644 --- a/PortabilityLayer/PLLabelWidget.cpp +++ b/PortabilityLayer/PLLabelWidget.cpp @@ -27,6 +27,6 @@ namespace PortabilityLayer const Point topLeftCorner = Point::Create(m_rect.left, m_rect.top); const Point textStartPoint = topLeftCorner + Point::Create(0, surface->MeasureFontAscender()); - surface->DrawStringWrap(textStartPoint, m_rect, m_text.ToShortStr()); + surface->DrawStringWrap(textStartPoint, m_rect, m_text.ToShortStr(), true); } } diff --git a/PortabilityLayer/PLQDraw.cpp b/PortabilityLayer/PLQDraw.cpp index a93da99..47a7005 100644 --- a/PortabilityLayer/PLQDraw.cpp +++ b/PortabilityLayer/PLQDraw.cpp @@ -498,7 +498,8 @@ void GetForeColor(RGBColor *color) *color = RGBColor(foreColor.r, foreColor.g, foreColor.b); } -static void DrawGlyph(PortabilityLayer::QDState *qdState, PixMap *pixMap, const Rect &rect, Point &penPos, const PortabilityLayer::RenderedFont *rfont, unsigned int character) +static void DrawGlyph(PortabilityLayer::QDState *qdState, PixMap *pixMap, const Rect &rect, Point &penPos, const PortabilityLayer::RenderedFont *rfont, unsigned int character, + PortabilityLayer::AntiAliasTable *&cachedAATable, PortabilityLayer::RGBAColor &cachedAATableColor) { assert(rect.IsValid()); @@ -537,12 +538,41 @@ static void DrawGlyph(PortabilityLayer::QDState *qdState, PixMap *pixMap, const const size_t outputPitch = pixMap->m_pitch; const uint8_t *firstInputRowData = static_cast(data) + firstInputRow * inputPitch; + const bool isAA = rfont->IsAntiAliased(); + switch (pixMap->m_pixelFormat) { case GpPixelFormats::k8BitStandard: { uint8_t *firstOutputRowData = static_cast(pixMap->m_data) + firstOutputRow * outputPitch; + const PortabilityLayer::AntiAliasTable *aaTable = nullptr; + + if (isAA) + { + const PortabilityLayer::RGBAColor foreColor = qdState->GetForeColor(); + if (foreColor == PortabilityLayer::RGBAColor::Create(0, 0, 0, 255)) + aaTable = &PortabilityLayer::StandardPalette::GetInstance()->GetBlackAATable(); + else if (foreColor == PortabilityLayer::RGBAColor::Create(255, 255, 255, 255)) + aaTable = &PortabilityLayer::StandardPalette::GetInstance()->GetWhiteAATable(); + else if (cachedAATable != nullptr && foreColor == cachedAATableColor) + aaTable = cachedAATable; + else + { + if (!cachedAATable) + { + cachedAATable = static_cast(PortabilityLayer::MemoryManager::GetInstance()->Alloc(sizeof(PortabilityLayer::AntiAliasTable))); + if (!cachedAATable) + return; + } + + cachedAATableColor = foreColor; + cachedAATable->GenerateForPalette(foreColor, PortabilityLayer::StandardPalette::GetInstance()->GetColors(), 256); + + aaTable = cachedAATable; + } + } + const uint8_t color = qdState->ResolveForeColor8(nullptr, 0); for (uint32_t row = 0; row < numRows; row++) { @@ -550,11 +580,26 @@ static void DrawGlyph(PortabilityLayer::QDState *qdState, PixMap *pixMap, const uint8_t *outputRowData = firstOutputRowData + row * outputPitch; // It should be possible to speed this up, if needed. The input is guaranteed to be well-aligned and not mutable within this loop. - for (uint32_t col = 0; col < numCols; col++) + if (isAA) { - const size_t inputOffset = firstInputCol + col; - if (inputRowData[inputOffset / 8] & (1 << (inputOffset & 0x7))) - outputRowData[firstOutputCol + col] = color; + for (uint32_t col = 0; col < numCols; col++) + { + const size_t inputOffset = firstInputCol + col; + + const unsigned int grayLevel = (inputRowData[inputOffset / 2] >> ((inputOffset & 1) * 4)) & 0xf; + uint8_t &targetPixel = outputRowData[firstOutputCol + col]; + + targetPixel = aaTable->m_aaTranslate[targetPixel][grayLevel]; + } + } + else + { + for (uint32_t col = 0; col < numCols; col++) + { + const size_t inputOffset = firstInputCol + col; + if (inputRowData[inputOffset / 8] & (1 << (inputOffset & 0x7))) + outputRowData[firstOutputCol + col] = color; + } } } } @@ -564,7 +609,7 @@ static void DrawGlyph(PortabilityLayer::QDState *qdState, PixMap *pixMap, const } } -void DrawSurface::DrawString(const Point &point, const PLPasStr &str) +void DrawSurface::DrawString(const Point &point, const PLPasStr &str, bool aa) { PortabilityLayer::QDPort *port = &m_port; @@ -576,7 +621,7 @@ void DrawSurface::DrawString(const Point &point, const PLPasStr &str) const int fontVariationFlags = qdState->m_fontVariationFlags; PortabilityLayer::FontFamily *fontFamily = qdState->m_fontFamily; - PortabilityLayer::RenderedFont *rfont = fontManager->GetRenderedFontFromFamily(fontFamily, fontSize, fontVariationFlags); + PortabilityLayer::RenderedFont *rfont = fontManager->GetRenderedFontFromFamily(fontFamily, fontSize, aa, fontVariationFlags); Point penPos = point; const size_t len = str.Length(); @@ -599,13 +644,13 @@ void DrawSurface::DrawString(const Point &point, const PLPasStr &str) penPos = paraStartPos; } else - DrawGlyph(qdState, pixMap, rect, penPos, rfont, chars[i]); + DrawGlyph(qdState, pixMap, rect, penPos, rfont, chars[i], m_cachedAATable, m_cachedAAColor); } m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents); } -void DrawSurface::DrawStringWrap(const Point &point, const Rect &constrainRect, const PLPasStr &str) +void DrawSurface::DrawStringWrap(const Point &point, const Rect &constrainRect, const PLPasStr &str, bool aa) { PortabilityLayer::QDPort *port = &m_port; @@ -617,7 +662,7 @@ void DrawSurface::DrawStringWrap(const Point &point, const Rect &constrainRect, const int fontVariationFlags = qdState->m_fontVariationFlags; PortabilityLayer::FontFamily *fontFamily = qdState->m_fontFamily; - PortabilityLayer::RenderedFont *rfont = fontManager->GetRenderedFontFromFamily(fontFamily, fontSize, fontVariationFlags); + PortabilityLayer::RenderedFont *rfont = fontManager->GetRenderedFontFromFamily(fontFamily, fontSize, aa, fontVariationFlags); Point penPos = point; const size_t len = str.Length(); @@ -703,7 +748,7 @@ void DrawSurface::DrawStringWrap(const Point &point, const Rect &constrainRect, { const uint8_t character = chars[currentStartChar + ci]; - DrawGlyph(qdState, pixMap, pixMap->m_rect, penPos, rfont, character); + DrawGlyph(qdState, pixMap, pixMap->m_rect, penPos, rfont, character, m_cachedAATable, m_cachedAAColor); } currentStartChar += committedLength; @@ -728,7 +773,7 @@ size_t DrawSurface::MeasureString(const PLPasStr &str) const int variationFlags = qdState->m_fontVariationFlags; const int fontSize = qdState->m_fontSize; - PortabilityLayer::RenderedFont *rfont = fontManager->GetRenderedFontFromFamily(fontFamily, fontSize, variationFlags); + PortabilityLayer::RenderedFont *rfont = fontManager->GetRenderedFontFromFamily(fontFamily, fontSize, false, variationFlags); if (!rfont) return 0; @@ -748,7 +793,7 @@ int32_t DrawSurface::MeasureFontAscender() const int variationFlags = qdState->m_fontVariationFlags; const int fontSize = qdState->m_fontSize; - PortabilityLayer::RenderedFont *rfont = fontManager->GetRenderedFontFromFamily(fontFamily, fontSize, variationFlags); + PortabilityLayer::RenderedFont *rfont = fontManager->GetRenderedFontFromFamily(fontFamily, fontSize, false, variationFlags); if (!rfont) return 0; @@ -768,7 +813,7 @@ int32_t DrawSurface::MeasureFontLineGap() const int variationFlags = qdState->m_fontVariationFlags; const int fontSize = qdState->m_fontSize; - PortabilityLayer::RenderedFont *rfont = fontManager->GetRenderedFontFromFamily(fontFamily, fontSize, variationFlags); + PortabilityLayer::RenderedFont *rfont = fontManager->GetRenderedFontFromFamily(fontFamily, fontSize, false, variationFlags); if (!rfont) return 0; diff --git a/PortabilityLayer/PLRadioButtonWidget.cpp b/PortabilityLayer/PLRadioButtonWidget.cpp index 272fefe..7422c76 100644 --- a/PortabilityLayer/PLRadioButtonWidget.cpp +++ b/PortabilityLayer/PLRadioButtonWidget.cpp @@ -43,7 +43,7 @@ namespace PortabilityLayer surface->SetForeColor(StdColors::Black()); surface->SetSystemFont(12, FontFamilyFlag_Bold); int32_t textV = (m_rect.top + m_rect.bottom + surface->MeasureFontAscender()) / 2; - surface->DrawString(Point::Create(m_rect.left + radioFrameSize + 2, textV), m_text.ToShortStr()); + surface->DrawString(Point::Create(m_rect.left + radioFrameSize + 2, textV), m_text.ToShortStr(), true); } void RadioButtonWidget::SetString(const PLPasStr &str) diff --git a/PortabilityLayer/PLResourceManager.cpp b/PortabilityLayer/PLResourceManager.cpp index ff7a405..db5c355 100644 --- a/PortabilityLayer/PLResourceManager.cpp +++ b/PortabilityLayer/PLResourceManager.cpp @@ -1,5 +1,6 @@ #include "ResourceManager.h" -#include "VirtualDirectory.h" + +#include "BMPFormat.h" #include "FileManager.h" #include "GPArchive.h" #include "HostFileSystem.h" @@ -14,10 +15,67 @@ #include "ResourceFile.h" #include "PLPasStr.h" #include "PLErrorCodes.h" +#include "VirtualDirectory.h" +#include "WaveFormat.h" #include "ZipFileProxy.h" #include +namespace ResourceValidationRules +{ + enum ResourceValidationRule + { + kNone, + kWAV, + kBMP, + }; +} + +typedef ResourceValidationRules::ResourceValidationRule ResourceValidationRule_t; + +namespace +{ + // Validation is only intended to validate enough of the file structure that constrained validation can be performed + // without needing to pass the file size + static bool ValidateResource(const void *res, size_t size, ResourceValidationRule_t validationRule) + { + switch (validationRule) + { + case ResourceValidationRules::kWAV: + { + if (size < sizeof(PortabilityLayer::RIFFTag)) + return false; + + PortabilityLayer::RIFFTag mainTag; + memcpy(&mainTag, res, sizeof(mainTag)); + if (mainTag.m_chunkSize > size - sizeof(sizeof(PortabilityLayer::RIFFTag))) + return false; + + return true; + } + break; + + case ResourceValidationRules::kBMP: + { + if (size < sizeof(PortabilityLayer::BitmapFileHeader)) + return false; + + PortabilityLayer::BitmapFileHeader mainHeader; + memcpy(&mainHeader, res, sizeof(mainHeader)); + if (mainHeader.m_fileSize > size) + return false; + + return true; + } + break; + + default: + break; + }; + } +} + + namespace PortabilityLayer { struct MMHandleBlock; @@ -315,6 +373,14 @@ namespace PortabilityLayer THandle ResourceArchive::GetResource(const ResTypeID &resTypeID, int id, bool load) { const char *extension = ".bin"; + ResourceValidationRule_t validationRule = ResourceValidationRules::kNone; + + if (resTypeID == ResTypeID('snd ')) + { + extension = ".wav"; + validationRule = ResourceValidationRules::kWAV; + } + char resourceFile[64]; GpArcResourceTypeTag resTag = GpArcResourceTypeTag::Encode(resTypeID); @@ -350,11 +416,13 @@ namespace PortabilityLayer handle->m_contents = contents; handle->m_size = ref->m_size; - if (!m_zipFileProxy->LoadFile(index, contents)) + if (!m_zipFileProxy->LoadFile(index, contents) || (validationRule != ResourceValidationRules::kNone && !ValidateResource(contents, ref->m_size, validationRule))) { MemoryManager::GetInstance()->Release(contents); handle->m_contents = nullptr; handle->m_size = 0; + + return THandle(); } } } diff --git a/PortabilityLayer/PLSound.cpp b/PortabilityLayer/PLSound.cpp index aa7df85..2da4fdc 100644 --- a/PortabilityLayer/PLSound.cpp +++ b/PortabilityLayer/PLSound.cpp @@ -7,6 +7,7 @@ #include "HostMutex.h" #include "HostSystemServices.h" #include "HostThreadEvent.h" +#include "WaveFormat.h" #include @@ -42,7 +43,7 @@ namespace PortabilityLayer ~AudioChannelImpl(); void Destroy(bool wait) override; - bool AddBuffer(const void *smBuffer, bool blocking) override; + bool AddBuffer(const void *lengthTaggedBuffer, bool blocking) override; bool AddCallback(AudioChannelCallback_t callback, bool blocking) override; void ClearAllCommands() override; void Stop() override; @@ -67,7 +68,6 @@ namespace PortabilityLayer void DigestBufferCommand(const void *dataPointer); PortabilityLayer::HostAudioChannel *m_audioChannel; - ; HostMutex *m_mutex; HostThreadEvent *m_threadEvent; @@ -145,11 +145,11 @@ namespace PortabilityLayer PortabilityLayer::MemoryManager::GetInstance()->Release(this); } - bool AudioChannelImpl::AddBuffer(const void *smBuffer, bool blocking) + bool AudioChannelImpl::AddBuffer(const void *lengthTaggedBuffer, bool blocking) { AudioCommand cmd; cmd.m_commandType = AudioCommandTypes::kBuffer; - cmd.m_param.m_ptr = smBuffer; + cmd.m_param.m_ptr = lengthTaggedBuffer; return this->PushCommand(cmd, blocking); } @@ -195,26 +195,11 @@ namespace PortabilityLayer void AudioChannelImpl::DigestBufferCommand(const void *dataPointer) { - struct BufferHeader - { - BEUInt32_t m_samplePtr; - BEUInt32_t m_length; - BEFixed32_t m_sampleRate; - BEUInt32_t m_loopStart; - BEUInt32_t m_loopEnd; - uint8_t m_encoding; - uint8_t m_baseFrequency; - }; + // At this point, the buffer should already be validated and converted, and the data pointer should point at the data tag + uint32_t length; + memcpy(&length, dataPointer, 4); - BufferHeader bufferHeader; - - GP_STATIC_ASSERT(sizeof(BufferHeader) >= 22); - - memcpy(&bufferHeader, dataPointer, 22); - - const uint32_t length = bufferHeader.m_length; - - m_audioChannel->PostBuffer(static_cast(dataPointer) + 22, length); + m_audioChannel->PostBuffer(static_cast(dataPointer) + 4, length); m_state = State_PlayingAsync; } diff --git a/PortabilityLayer/PLSound.h b/PortabilityLayer/PLSound.h index 80cb556..4c2d528 100644 --- a/PortabilityLayer/PLSound.h +++ b/PortabilityLayer/PLSound.h @@ -11,7 +11,7 @@ namespace PortabilityLayer struct AudioChannel { virtual void Destroy(bool wait) = 0; - virtual bool AddBuffer(const void *smBuffer, bool blocking) = 0; + virtual bool AddBuffer(const void *lengthTaggedBuffer, bool blocking) = 0; virtual bool AddCallback(AudioChannelCallback_t callback, bool blocking) = 0; virtual void ClearAllCommands() = 0; virtual void Stop() = 0; diff --git a/PortabilityLayer/PortabilityLayer.vcxproj b/PortabilityLayer/PortabilityLayer.vcxproj index 4fede5b..6e27ee9 100644 --- a/PortabilityLayer/PortabilityLayer.vcxproj +++ b/PortabilityLayer/PortabilityLayer.vcxproj @@ -138,6 +138,7 @@ + @@ -289,6 +290,7 @@ + diff --git a/PortabilityLayer/PortabilityLayer.vcxproj.filters b/PortabilityLayer/PortabilityLayer.vcxproj.filters index 35b8d6a..7cb4cf1 100644 --- a/PortabilityLayer/PortabilityLayer.vcxproj.filters +++ b/PortabilityLayer/PortabilityLayer.vcxproj.filters @@ -465,6 +465,9 @@ Header Files + + Header Files + @@ -725,5 +728,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/PortabilityLayer/QDGraf.cpp b/PortabilityLayer/QDGraf.cpp index 4842040..03e24d2 100644 --- a/PortabilityLayer/QDGraf.cpp +++ b/PortabilityLayer/QDGraf.cpp @@ -1,4 +1,6 @@ #include "QDGraf.h" + +#include "MemoryManager.h" #include "QDPixMap.h" #include "QDPort.h" #include "IGpDisplayDriver.h" @@ -6,6 +8,8 @@ DrawSurface::~DrawSurface() { + if (m_cachedAATable) + PortabilityLayer::MemoryManager::GetInstance()->Release(m_cachedAATable); } void DrawSurface::PushToDDSurface(IGpDisplayDriver *displayDriver) diff --git a/PortabilityLayer/QDGraf.h b/PortabilityLayer/QDGraf.h index bb83276..bdcb963 100644 --- a/PortabilityLayer/QDGraf.h +++ b/PortabilityLayer/QDGraf.h @@ -9,6 +9,7 @@ namespace PortabilityLayer { + struct AntiAliasTable; class FontFamily; struct RGBAColor; class ScanlineMask; @@ -27,12 +28,16 @@ struct DrawSurface final DrawSurface() : m_port(PortabilityLayer::QDPortType_DrawSurface) , m_ddSurface(nullptr) + , m_cachedAAColor(PortabilityLayer::RGBAColor::Create(0, 0, 0, 255)) + , m_cachedAATable(nullptr) { } explicit DrawSurface(PortabilityLayer::QDPortType overridePortType) : m_port(overridePortType) , m_ddSurface(nullptr) + , m_cachedAAColor(PortabilityLayer::RGBAColor::Create(0, 0, 0, 255)) + , m_cachedAATable(nullptr) { } @@ -76,8 +81,8 @@ struct DrawSurface final void SetApplicationFont(int size, int variationFlags); void SetSystemFont(int size, int variationFlags); - void DrawString(const Point &point, const PLPasStr &str); - void DrawStringWrap(const Point &point, const Rect &constrainRect, const PLPasStr &str); + void DrawString(const Point &point, const PLPasStr &str, bool aa); + void DrawStringWrap(const Point &point, const Rect &constrainRect, const PLPasStr &str, bool aa); size_t MeasureString(const PLPasStr &str); int32_t MeasureFontAscender(); @@ -93,8 +98,13 @@ struct DrawSurface final Rect GetClipRect() const; void SetClipRect(const Rect &rect); + void RegenerateAATable(const PortabilityLayer::RGBAColor &color, const PortabilityLayer::RGBAColor *paletteColors, size_t numColors); + // Must be the first item PortabilityLayer::QDPort m_port; IGpDisplayDriverSurface *m_ddSurface; + + PortabilityLayer::AntiAliasTable *m_cachedAATable; + PortabilityLayer::RGBAColor m_cachedAAColor; }; diff --git a/PortabilityLayer/QDStandardPalette.cpp b/PortabilityLayer/QDStandardPalette.cpp index c72a762..58f9298 100644 --- a/PortabilityLayer/QDStandardPalette.cpp +++ b/PortabilityLayer/QDStandardPalette.cpp @@ -81,7 +81,35 @@ namespace PortabilityLayer for (unsigned int rs = 0; rs < 16; rs++) for (unsigned int gs = 0; gs < 16; gs++) for (unsigned int bs = 0; bs < 16; bs++) - m_lut[rs + (gs << 4) + (bs << 8)] = MapColorAnalyticTruncated(rs, gs, bs); + m_lut[rs + (gs << 4) + (bs << 8)] = MapColorAnalyticTruncated(rs, gs, bs); + + for (unsigned int i = 0; i < 256; i++) + { + unsigned int shortChannels[3] = + { + m_colors[i].r / 17, + m_colors[i].g / 17, + m_colors[i].b / 17 + }; + + for (unsigned int b = 0; b < 16; b++) + { + unsigned int whiteScale[3]; + unsigned int blackScale[3]; + + for (unsigned int ch = 0; ch < 3; ch++) + { + unsigned int scaledBackground = (15 - b) * shortChannels[ch]; + unsigned int scaledWhiteForeground = 15 * b; + + blackScale[ch] = scaledBackground / 15; + whiteScale[ch] = (scaledBackground + scaledWhiteForeground) / 15; + } + + m_blackAATable.m_aaTranslate[i][b] = MapColorAnalyticTruncated(blackScale[0], blackScale[1], blackScale[2]); + m_whiteAATable.m_aaTranslate[i][b] = MapColorAnalyticTruncated(whiteScale[0], whiteScale[1], whiteScale[2]); + } + } } const RGBAColor *StandardPalette::GetColors() const @@ -228,6 +256,16 @@ namespace PortabilityLayer const StandardPalette *StandardPalette::GetInstance() { return &ms_instance; + } + + const AntiAliasTable &StandardPalette::GetWhiteAATable() const + { + return m_whiteAATable; + } + + const AntiAliasTable &StandardPalette::GetBlackAATable() const + { + return m_blackAATable; } StandardPalette StandardPalette::ms_instance; diff --git a/PortabilityLayer/QDStandardPalette.h b/PortabilityLayer/QDStandardPalette.h index 06be3c6..83b5f88 100644 --- a/PortabilityLayer/QDStandardPalette.h +++ b/PortabilityLayer/QDStandardPalette.h @@ -1,9 +1,12 @@ #pragma once - + +#include "AntiAliasTable.h" #include "RGBAColor.h" namespace PortabilityLayer -{ +{ + struct AntiAliasTable; + class StandardPalette { public: @@ -16,14 +19,18 @@ namespace PortabilityLayer static uint8_t MapColorAnalytic(uint8_t r, uint8_t g, uint8_t b); static uint8_t MapColorAnalytic(const RGBAColor &color); uint8_t MapColorLUT(uint8_t r, uint8_t g, uint8_t b) const; - uint8_t MapColorLUT(const RGBAColor &color) const; + uint8_t MapColorLUT(const RGBAColor &color) const; + const AntiAliasTable &GetWhiteAATable() const; + const AntiAliasTable &GetBlackAATable() const; static const StandardPalette *GetInstance(); private: static StandardPalette ms_instance; - RGBAColor m_colors[kSize]; + RGBAColor m_colors[kSize]; + AntiAliasTable m_whiteAATable; + AntiAliasTable m_blackAATable; uint8_t m_lut[16 * 16 * 16]; }; } diff --git a/PortabilityLayer/RGBAColor.h b/PortabilityLayer/RGBAColor.h index 36a5a7d..402687d 100644 --- a/PortabilityLayer/RGBAColor.h +++ b/PortabilityLayer/RGBAColor.h @@ -8,6 +8,8 @@ namespace PortabilityLayer { uint8_t r, g, b, a; + bool operator==(const RGBAColor &other) const; + bool operator!=(const RGBAColor &other) const; static RGBAColor Create(uint8_t r, uint8_t g, uint8_t b, uint8_t a); }; @@ -20,5 +22,15 @@ namespace PortabilityLayer color.a = a; return color; + } + + inline bool RGBAColor::operator==(const RGBAColor &other) const + { + return this->r == other.r && this->g == other.g && this->b == other.b && this->a == other.a; + } + + inline bool RGBAColor::operator!=(const RGBAColor &other) const + { + return !((*this) == other); } } diff --git a/PortabilityLayer/RenderedFont.h b/PortabilityLayer/RenderedFont.h index 39dfa00..62fba46 100644 --- a/PortabilityLayer/RenderedFont.h +++ b/PortabilityLayer/RenderedFont.h @@ -14,6 +14,7 @@ namespace PortabilityLayer virtual bool GetGlyph(unsigned int character, const RenderedGlyphMetrics *&outMetricsPtr, const void *&outData) const = 0; virtual const RenderedFontMetrics &GetMetrics() const = 0; virtual size_t MeasureString(const uint8_t *chars, size_t len) const = 0; + virtual bool IsAntiAliased() const = 0; virtual void Destroy() = 0; }; diff --git a/PortabilityLayer/WaveFormat.h b/PortabilityLayer/WaveFormat.h index 825aeb8..d322e53 100644 --- a/PortabilityLayer/WaveFormat.h +++ b/PortabilityLayer/WaveFormat.h @@ -1,6 +1,6 @@ #pragma once -#include "PLLittleEndian.h" +#include "PLLittleEndian.h" namespace PortabilityLayer { @@ -10,9 +10,9 @@ namespace PortabilityLayer static const uint32_t kRiffChunkID = 0x46464952; static const uint32_t kWaveChunkID = 0x45564157; static const uint32_t kFormatChunkID = 0x20746d66; - static const uint32_t kDataChunkID = 0x61746164; + static const uint32_t kDataChunkID = 0x61746164; } - + struct RIFFTag { LEUInt32_t m_tag; diff --git a/gpr2gpa/gpr2gpa.cpp b/gpr2gpa/gpr2gpa.cpp index 10b807a..3b46a68 100644 --- a/gpr2gpa/gpr2gpa.cpp +++ b/gpr2gpa/gpr2gpa.cpp @@ -490,8 +490,8 @@ bool BMPDumperContext::Export(std::vector &outData) const PortabilityLayer::BitmapFileHeader fileHeader; fileHeader.m_id[0] = 'B'; fileHeader.m_id[1] = 'M'; - fileHeader.m_fileSize = imageFileSize; - fileHeader.m_imageDataStart = fileHeaderSize + infoHeaderSize + ctabSize + postCTabPaddingSize; + fileHeader.m_fileSize = static_cast(imageFileSize); + fileHeader.m_imageDataStart = static_cast(fileHeaderSize + infoHeaderSize + ctabSize + postCTabPaddingSize); fileHeader.m_reserved1 = 0; fileHeader.m_reserved2 = 0; @@ -499,12 +499,12 @@ bool BMPDumperContext::Export(std::vector &outData) const PortabilityLayer::BitmapInfoHeader infoHeader; infoHeader.m_thisStructureSize = sizeof(infoHeader); - infoHeader.m_width = width; - infoHeader.m_height = height; + infoHeader.m_width = static_cast(width); + infoHeader.m_height = static_cast(height); infoHeader.m_planes = 1; infoHeader.m_bitsPerPixel = bpp; infoHeader.m_compression = PortabilityLayer::BitmapConstants::kCompressionRGB; - infoHeader.m_imageSize = imageDataSize; + infoHeader.m_imageSize = static_cast(imageDataSize); infoHeader.m_xPixelsPerMeter = 2835; infoHeader.m_yPixelsPerMeter = 2835; infoHeader.m_numColors = (bpp < 16) ? numColors : 0; @@ -669,7 +669,7 @@ bool ImportSound(std::vector &outWAV, const void *inData, size_t inSize PortabilityLayer::RIFFTag riffTag; riffTag.m_tag = PortabilityLayer::WaveConstants::kRiffChunkID; - riffTag.m_chunkSize = waveMarkerSize + fmtTagSize + fmtContentSize + dataTagSize + dataContentSize; + riffTag.m_chunkSize = static_cast(waveMarkerSize + fmtTagSize + fmtContentSize + dataTagSize + dataContentSize); VectorAppend(outWAV, reinterpret_cast(&riffTag), sizeof(riffTag)); @@ -770,7 +770,9 @@ int main(int argc, const char **argv) if (ImportPICT(entry.m_contents, resData, resSize)) contents.push_back(entry); } - else if (typeList.m_resType == sndTypeID) + else +#endif + if (typeList.m_resType == sndTypeID) { PlannedEntry entry; char resName[256]; @@ -782,7 +784,6 @@ int main(int argc, const char **argv) contents.push_back(entry); } else -#endif { PlannedEntry entry;