mirror of
https://github.com/vcmi/vcmi.git
synced 2025-02-09 13:14:02 +02:00
Merge branch 'develop' into chinese
This commit is contained in:
commit
4b6f8293c2
2
.github/workflows/github.yml
vendored
2
.github/workflows/github.yml
vendored
@ -352,7 +352,7 @@ jobs:
|
||||
run: |
|
||||
find . -path ./.git -prune -o -path ./AI/FuzzyLite -prune -o -path ./test/googletest \
|
||||
-o -path ./osx -prune -o -type f \
|
||||
-not -name '*.png' -and -not -name '*.vcxproj*' -and -not -name '*.props' -and -not -name '*.wav' -and -not -name '*.webm' -and -not -name '*.ico' -and -not -name '*.bat' -print0 | \
|
||||
-not -name '*.png' -and -not -name '*.ttf' -and -not -name '*.wav' -and -not -name '*.webm' -and -not -name '*.ico' -and -not -name '*.bat' -print0 | \
|
||||
{ ! xargs -0 grep -l -z -P '\r\n'; }
|
||||
|
||||
- name: Validate JSON
|
||||
|
BIN
Mods/vcmi/Data/NotoSans-Medium.ttf
Normal file
BIN
Mods/vcmi/Data/NotoSans-Medium.ttf
Normal file
Binary file not shown.
BIN
Mods/vcmi/Data/NotoSerif-Black.ttf
Normal file
BIN
Mods/vcmi/Data/NotoSerif-Black.ttf
Normal file
Binary file not shown.
BIN
Mods/vcmi/Data/NotoSerif-Bold.ttf
Normal file
BIN
Mods/vcmi/Data/NotoSerif-Bold.ttf
Normal file
Binary file not shown.
BIN
Mods/vcmi/Data/NotoSerif-Medium.ttf
Normal file
BIN
Mods/vcmi/Data/NotoSerif-Medium.ttf
Normal file
Binary file not shown.
@ -95,10 +95,10 @@ set(vcmiclientcommon_SRCS
|
||||
render/ImageLocator.cpp
|
||||
|
||||
renderSDL/CBitmapFont.cpp
|
||||
renderSDL/CBitmapHanFont.cpp
|
||||
renderSDL/CTrueTypeFont.cpp
|
||||
renderSDL/CursorHardware.cpp
|
||||
renderSDL/CursorSoftware.cpp
|
||||
renderSDL/FontChain.cpp
|
||||
renderSDL/ImageScaled.cpp
|
||||
renderSDL/RenderHandler.cpp
|
||||
renderSDL/SDLImage.cpp
|
||||
@ -303,10 +303,10 @@ set(vcmiclientcommon_HEADERS
|
||||
render/IScreenHandler.h
|
||||
|
||||
renderSDL/CBitmapFont.h
|
||||
renderSDL/CBitmapHanFont.h
|
||||
renderSDL/CTrueTypeFont.h
|
||||
renderSDL/CursorHardware.h
|
||||
renderSDL/CursorSoftware.h
|
||||
renderSDL/FontChain.h
|
||||
renderSDL/ImageScaled.h
|
||||
renderSDL/RenderHandler.h
|
||||
renderSDL/SDLImage.h
|
||||
|
@ -112,9 +112,10 @@ std::vector<std::string> BattleConsole::splitText(const std::string &text)
|
||||
|
||||
boost::split(lines, text, boost::is_any_of("\n"));
|
||||
|
||||
const auto & font = GH.renderHandler().loadFont(FONT_SMALL);
|
||||
for(const auto & line : lines)
|
||||
{
|
||||
if (graphics->fonts[FONT_SMALL]->getStringWidth(text) < pos.w)
|
||||
if (font->getStringWidth(text) < pos.w)
|
||||
{
|
||||
output.push_back(line);
|
||||
}
|
||||
@ -1098,7 +1099,8 @@ void StackQueue::StackBox::setUnit(const battle::Unit * unit, size_t turn, std::
|
||||
if(currentTurn && !owner->embedded)
|
||||
{
|
||||
std::string tmp = std::to_string(*currentTurn);
|
||||
int len = graphics->fonts[FONT_SMALL]->getStringWidth(tmp);
|
||||
const auto & font = GH.renderHandler().loadFont(FONT_SMALL);
|
||||
int len = font->getStringWidth(tmp);
|
||||
roundRect->pos.w = len + 6;
|
||||
round->setText(tmp);
|
||||
}
|
||||
|
@ -17,7 +17,9 @@
|
||||
#include "../render/Colors.h"
|
||||
#include "../render/EFont.h"
|
||||
#include "../render/IFont.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
#include "../gui/TextAlignment.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../render/Graphics.h"
|
||||
|
||||
BattleOverlayLogVisualizer::BattleOverlayLogVisualizer(
|
||||
@ -30,7 +32,8 @@ BattleOverlayLogVisualizer::BattleOverlayLogVisualizer(
|
||||
void BattleOverlayLogVisualizer::drawText(BattleHex hex, int lineNumber, const std::string & text)
|
||||
{
|
||||
Point offset = owner.fieldController->hexPositionLocal(hex).topLeft() + Point(20, 20);
|
||||
int h = graphics->fonts[EFonts::FONT_TINY]->getLineHeight();
|
||||
const auto & font = GH.renderHandler().loadFont(FONT_TINY);
|
||||
int h = font->getLineHeight();
|
||||
|
||||
offset.y += h * lineNumber;
|
||||
|
||||
|
@ -318,10 +318,10 @@ void BattleStacksController::showStackAmountBox(Canvas & canvas, const CStack *
|
||||
boxPosition = owner.fieldController->hexPositionLocal(frontPos).center() + Point(-8, -14);
|
||||
}
|
||||
|
||||
Point textPosition = Point(amountBG->dimensions().x/2 + boxPosition.x, boxPosition.y + graphics->fonts[EFonts::FONT_TINY]->getLineHeight() - 6);
|
||||
Point textPosition = Point(amountBG->dimensions().x/2 + boxPosition.x, boxPosition.y + amountBG->dimensions().y/2);
|
||||
|
||||
canvas.draw(amountBG, boxPosition);
|
||||
canvas.drawText(textPosition, EFonts::FONT_TINY, Colors::WHITE, ETextAlignment::TOPCENTER, TextOperations::formatMetric(stack->getCount(), 4));
|
||||
canvas.drawText(textPosition, EFonts::FONT_TINY, Colors::WHITE, ETextAlignment::CENTER, TextOperations::formatMetric(stack->getCount(), 4));
|
||||
}
|
||||
|
||||
void BattleStacksController::showStack(Canvas & canvas, const CStack * stack)
|
||||
|
@ -192,7 +192,8 @@ void CGuiHandler::drawFPSCounter()
|
||||
|
||||
std::string fps = std::to_string(framerate().getFramerate())+" FPS";
|
||||
|
||||
graphics->fonts[FONT_SMALL]->renderTextLeft(screen, fps, Colors::WHITE, Point(8 * scaling, screen->h-22 * scaling));
|
||||
const auto & font = GH.renderHandler().loadFont(FONT_SMALL);
|
||||
font->renderTextLeft(screen, fps, Colors::WHITE, Point(8 * scaling, screen->h-22 * scaling));
|
||||
}
|
||||
|
||||
bool CGuiHandler::amIGuiThread()
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "../gui/Shortcut.h"
|
||||
#include "../render/Graphics.h"
|
||||
#include "../render/IFont.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
#include "../widgets/ComboBox.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
@ -284,7 +285,7 @@ EFonts InterfaceObjectConfigurable::readFont(const JsonNode & config) const
|
||||
return EFonts::FONT_CALLI;
|
||||
}
|
||||
logGlobal->debug("Unknown font attribute");
|
||||
return EFonts::FONT_TIMES;
|
||||
return EFonts::FONT_MEDIUM;
|
||||
}
|
||||
|
||||
std::pair<std::string, std::string> InterfaceObjectConfigurable::readHintText(const JsonNode & config) const
|
||||
@ -357,8 +358,9 @@ std::shared_ptr<CMultiLineLabel> InterfaceObjectConfigurable::buildMultiLineLabe
|
||||
auto color = readColor(config["color"]);
|
||||
auto text = readText(config["text"]);
|
||||
Rect rect = readRect(config["rect"]);
|
||||
const auto & fontPtr = GH.renderHandler().loadFont(font);
|
||||
if(!config["adoptHeight"].isNull() && config["adoptHeight"].Bool())
|
||||
rect.h = graphics->fonts[font]->getLineHeight() * 2;
|
||||
rect.h = fontPtr->getLineHeight() * 2;
|
||||
return std::make_shared<CMultiLineLabel>(rect, font, alignment, color, text);
|
||||
}
|
||||
|
||||
|
@ -256,15 +256,17 @@ void InfoCard::changeSelection()
|
||||
if(!showChat)
|
||||
labelGroupPlayers->disable();
|
||||
|
||||
const auto & font = GH.renderHandler().loadFont(FONT_SMALL);
|
||||
|
||||
for(const auto & p : CSH->playerNames)
|
||||
{
|
||||
int slotsUsed = labelGroupPlayers->currentSize();
|
||||
Point labelPosition;
|
||||
|
||||
if(slotsUsed < 4)
|
||||
labelPosition = Point(24, 285 + slotsUsed * graphics->fonts[FONT_SMALL]->getLineHeight()); // left column
|
||||
labelPosition = Point(24, 285 + slotsUsed * font->getLineHeight()); // left column
|
||||
else
|
||||
labelPosition = Point(193, 285 + (slotsUsed - 4) * graphics->fonts[FONT_SMALL]->getLineHeight()); // right column
|
||||
labelPosition = Point(193, 285 + (slotsUsed - 4) * font->getLineHeight()); // right column
|
||||
|
||||
labelGroupPlayers->add(labelPosition.x, labelPosition.y, p.second.name);
|
||||
}
|
||||
@ -358,7 +360,8 @@ CChatBox::CChatBox(const Rect & rect)
|
||||
pos += rect.topLeft();
|
||||
setRedrawParent(true);
|
||||
|
||||
const int height = static_cast<int>(graphics->fonts[FONT_SMALL]->getLineHeight());
|
||||
const auto & font = GH.renderHandler().loadFont(FONT_SMALL);
|
||||
const int height = font->getLineHeight();
|
||||
Rect textInputArea(1, rect.h - height, rect.w - 1, height);
|
||||
Rect chatHistoryArea(3, 1, rect.w - 3, rect.h - height - 1);
|
||||
inputBackground = std::make_shared<TransparentFilledRectangle>(textInputArea, ColorRGBA(0,0,0,192));
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "../gui/WindowHandler.h"
|
||||
#include "../render/Graphics.h"
|
||||
#include "../render/IFont.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
#include "../media/ISoundPlayer.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
#include "../widgets/ComboBox.h"
|
||||
@ -1034,12 +1035,14 @@ OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry(const PlayerSettings & S, con
|
||||
labelPlayerNameEdit = std::make_shared<CTextInput>(Rect(6, 3, 95, 15), EFonts::FONT_SMALL, ETextAlignment::CENTER, false);
|
||||
labelPlayerNameEdit->setText(name);
|
||||
}
|
||||
labelWhoCanPlay = std::make_shared<CMultiLineLabel>(Rect(6, 23, 45, (int)graphics->fonts[EFonts::FONT_TINY]->getLineHeight()*2), EFonts::FONT_TINY, ETextAlignment::CENTER, Colors::WHITE, CGI->generaltexth->arraytxt[206 + whoCanPlay]);
|
||||
const auto & font = GH.renderHandler().loadFont(FONT_SMALL);
|
||||
|
||||
labelWhoCanPlay = std::make_shared<CMultiLineLabel>(Rect(6, 23, 45, font->getLineHeight()*2), EFonts::FONT_TINY, ETextAlignment::CENTER, Colors::WHITE, CGI->generaltexth->arraytxt[206 + whoCanPlay]);
|
||||
|
||||
auto hasHandicap = [this](){ return s->handicap.startBonus.empty() && s->handicap.percentIncome == 100 && s->handicap.percentGrowth == 100; };
|
||||
std::string labelHandicapText = hasHandicap() ? CGI->generaltexth->arraytxt[210] : MetaString::createFromTextID("vcmi.lobby.handicap").toString();
|
||||
labelHandicap = std::make_shared<CMultiLineLabel>(Rect(57, 24, 47, (int)graphics->fonts[EFonts::FONT_TINY]->getLineHeight()*2), EFonts::FONT_TINY, ETextAlignment::CENTER, Colors::WHITE, labelHandicapText);
|
||||
handicap = std::make_shared<LRClickableArea>(Rect(56, 24, 49, (int)graphics->fonts[EFonts::FONT_TINY]->getLineHeight()*2), [](){
|
||||
labelHandicap = std::make_shared<CMultiLineLabel>(Rect(57, 24, 47, font->getLineHeight()*2), EFonts::FONT_TINY, ETextAlignment::CENTER, Colors::WHITE, labelHandicapText);
|
||||
handicap = std::make_shared<LRClickableArea>(Rect(56, 24, 49, font->getLineHeight()*2), [](){
|
||||
if(!CSH->isHost())
|
||||
return;
|
||||
|
||||
|
@ -17,8 +17,10 @@
|
||||
#include "../render/Colors.h"
|
||||
#include "../render/EFont.h"
|
||||
#include "../render/IFont.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
#include "../render/Graphics.h"
|
||||
#include "../gui/TextAlignment.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
|
||||
|
||||
MapOverlayLogVisualizer::MapOverlayLogVisualizer(Canvas & target, std::shared_ptr<MapViewModel> model)
|
||||
@ -78,8 +80,10 @@ void MapOverlayLogVisualizer::drawText(
|
||||
|
||||
if(viewPort.isInside(pStart))
|
||||
{
|
||||
int w = graphics->fonts[EFonts::FONT_TINY]->getStringWidth(text);
|
||||
int h = graphics->fonts[EFonts::FONT_TINY]->getLineHeight();
|
||||
const auto & font = GH.renderHandler().loadFont(FONT_TINY);
|
||||
|
||||
int w = font->getStringWidth(text);
|
||||
int h = font->getLineHeight();
|
||||
|
||||
pStart.y += h * lineNumber;
|
||||
|
||||
|
@ -188,6 +188,8 @@ void MapViewCache::render(const std::shared_ptr<IMapRendererContext> & context,
|
||||
|
||||
if(context->showTextOverlay())
|
||||
{
|
||||
const auto & font = GH.renderHandler().loadFont(FONT_TINY);
|
||||
|
||||
for(int y = dimensions.top(); y < dimensions.bottom(); ++y)
|
||||
{
|
||||
for(int x = dimensions.left(); x < dimensions.right(); ++x)
|
||||
@ -204,8 +206,6 @@ void MapViewCache::render(const std::shared_ptr<IMapRendererContext> & context,
|
||||
else
|
||||
position.y -= targetRect.h / 4;
|
||||
|
||||
const auto font = graphics->fonts[EFonts::FONT_TINY];
|
||||
|
||||
Point dimensions(font->getStringWidth(overlay), font->getLineHeight());
|
||||
Rect textRect = Rect(position - dimensions / 2, dimensions).resize(2);
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "Canvas.h"
|
||||
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
#include "../render/IScreenHandler.h"
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
#include "Colors.h"
|
||||
@ -169,23 +170,27 @@ void Canvas::drawBorderDashed(const Rect & target, const ColorRGBA & color)
|
||||
|
||||
void Canvas::drawText(const Point & position, const EFonts & font, const ColorRGBA & colorDest, ETextAlignment alignment, const std::string & text )
|
||||
{
|
||||
const auto & fontPtr = GH.renderHandler().loadFont(font);
|
||||
|
||||
switch (alignment)
|
||||
{
|
||||
case ETextAlignment::TOPLEFT: return graphics->fonts[font]->renderTextLeft (surface, text, colorDest, transformPos(position));
|
||||
case ETextAlignment::TOPCENTER: return graphics->fonts[font]->renderTextCenter(surface, text, colorDest, transformPos(position));
|
||||
case ETextAlignment::CENTER: return graphics->fonts[font]->renderTextCenter(surface, text, colorDest, transformPos(position));
|
||||
case ETextAlignment::BOTTOMRIGHT: return graphics->fonts[font]->renderTextRight (surface, text, colorDest, transformPos(position));
|
||||
case ETextAlignment::TOPLEFT: return fontPtr->renderTextLeft (surface, text, colorDest, transformPos(position));
|
||||
case ETextAlignment::TOPCENTER: return fontPtr->renderTextCenter(surface, text, colorDest, transformPos(position));
|
||||
case ETextAlignment::CENTER: return fontPtr->renderTextCenter(surface, text, colorDest, transformPos(position));
|
||||
case ETextAlignment::BOTTOMRIGHT: return fontPtr->renderTextRight (surface, text, colorDest, transformPos(position));
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::drawText(const Point & position, const EFonts & font, const ColorRGBA & colorDest, ETextAlignment alignment, const std::vector<std::string> & text )
|
||||
{
|
||||
const auto & fontPtr = GH.renderHandler().loadFont(font);
|
||||
|
||||
switch (alignment)
|
||||
{
|
||||
case ETextAlignment::TOPLEFT: return graphics->fonts[font]->renderTextLinesLeft (surface, text, colorDest, transformPos(position));
|
||||
case ETextAlignment::TOPCENTER: return graphics->fonts[font]->renderTextLinesCenter(surface, text, colorDest, transformPos(position));
|
||||
case ETextAlignment::CENTER: return graphics->fonts[font]->renderTextLinesCenter(surface, text, colorDest, transformPos(position));
|
||||
case ETextAlignment::BOTTOMRIGHT: return graphics->fonts[font]->renderTextLinesRight (surface, text, colorDest, transformPos(position));
|
||||
case ETextAlignment::TOPLEFT: return fontPtr->renderTextLinesLeft (surface, text, colorDest, transformPos(position));
|
||||
case ETextAlignment::TOPCENTER: return fontPtr->renderTextLinesCenter(surface, text, colorDest, transformPos(position));
|
||||
case ETextAlignment::CENTER: return fontPtr->renderTextLinesCenter(surface, text, colorDest, transformPos(position));
|
||||
case ETextAlignment::BOTTOMRIGHT: return fontPtr->renderTextLinesRight (surface, text, colorDest, transformPos(position));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
struct SDL_Surface;
|
||||
class IImage;
|
||||
enum EFonts : int;
|
||||
enum EFonts : int8_t;
|
||||
|
||||
enum class CanvasScalingPolicy
|
||||
{
|
||||
|
@ -9,7 +9,15 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
enum EFonts : int
|
||||
enum EFonts : int8_t
|
||||
{
|
||||
FONT_BIG, FONT_CALLI, FONT_CREDITS, FONT_HIGH_SCORE, FONT_MEDIUM, FONT_SMALL, FONT_TIMES, FONT_TINY, FONT_VERD
|
||||
FONT_BIG,
|
||||
FONT_CALLI,
|
||||
FONT_CREDITS,
|
||||
FONT_HIGH_SCORE,
|
||||
FONT_MEDIUM,
|
||||
FONT_SMALL,
|
||||
FONT_TIMES,
|
||||
FONT_TINY,
|
||||
FONT_VERD
|
||||
};
|
||||
|
@ -19,25 +19,15 @@
|
||||
#include <vcmi/spells/Service.h>
|
||||
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
#include "../renderSDL/CBitmapFont.h"
|
||||
#include "../renderSDL/CBitmapHanFont.h"
|
||||
#include "../renderSDL/CTrueTypeFont.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/IImage.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
|
||||
#include "../lib/filesystem/Filesystem.h"
|
||||
#include "../lib/filesystem/CBinaryReader.h"
|
||||
#include "../../lib/json/JsonNode.h"
|
||||
#include "../lib/modding/CModHandler.h"
|
||||
#include "../lib/modding/ModScope.h"
|
||||
#include "CGameInfo.h"
|
||||
#include "../lib/VCMI_Lib.h"
|
||||
#include "../CCallback.h"
|
||||
#include "../lib/texts/CGeneralTextHandler.h"
|
||||
#include "../lib/vcmi_endian.h"
|
||||
#include "../lib/CStopWatch.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
|
||||
#include <SDL_surface.h>
|
||||
@ -127,7 +117,6 @@ void Graphics::initializeBattleGraphics()
|
||||
}
|
||||
Graphics::Graphics()
|
||||
{
|
||||
loadFonts();
|
||||
loadPaletteAndColors();
|
||||
initializeBattleGraphics();
|
||||
loadErmuToPicture();
|
||||
@ -166,29 +155,6 @@ void Graphics::setPlayerFlagColor(SDL_Palette * targetPalette, PlayerColor playe
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::loadFonts()
|
||||
{
|
||||
const JsonNode config(JsonPath::builtin("config/fonts.json"));
|
||||
|
||||
const JsonVector & bmpConf = config["bitmap"].Vector();
|
||||
const JsonNode & ttfConf = config["trueType"];
|
||||
const JsonNode & hanConf = config["bitmapHan"];
|
||||
|
||||
assert(bmpConf.size() == FONTS_NUMBER);
|
||||
|
||||
for (size_t i=0; i<FONTS_NUMBER; i++)
|
||||
{
|
||||
std::string filename = bmpConf[i].String();
|
||||
|
||||
if (!hanConf[filename].isNull())
|
||||
fonts[i] = std::make_shared<CBitmapHanFont>(hanConf[filename]);
|
||||
else if (!ttfConf[filename].isNull()) // no ttf override
|
||||
fonts[i] = std::make_shared<CTrueTypeFont>(ttfConf[filename]);
|
||||
else
|
||||
fonts[i] = std::make_shared<CBitmapFont>(filename);
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::loadErmuToPicture()
|
||||
{
|
||||
//loading ERMU to picture
|
||||
|
@ -9,26 +9,11 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../lib/GameConstants.h"
|
||||
#include "../lib/constants/NumericConstants.h"
|
||||
#include "../lib/constants/EntityIdentifiers.h"
|
||||
#include "../lib/Color.h"
|
||||
#include "../lib/filesystem/ResourcePath.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class CGHeroInstance;
|
||||
class CGTownInstance;
|
||||
class CHeroClass;
|
||||
struct InfoAboutHero;
|
||||
struct InfoAboutTown;
|
||||
class CGObjectInstance;
|
||||
class ObjectTemplate;
|
||||
class EntityService;
|
||||
class JsonNode;
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
struct SDL_Palette;
|
||||
class IFont;
|
||||
|
||||
/// Handles fonts, hero images, town images, various graphics
|
||||
class Graphics
|
||||
@ -36,13 +21,8 @@ class Graphics
|
||||
void initializeBattleGraphics();
|
||||
void loadPaletteAndColors();
|
||||
void loadErmuToPicture();
|
||||
void loadFonts();
|
||||
|
||||
public:
|
||||
//Fonts
|
||||
static const int FONTS_NUMBER = 9;
|
||||
std::array< std::shared_ptr<IFont>, FONTS_NUMBER> fonts;
|
||||
|
||||
using PlayerPalette = std::array<ColorRGBA, 32>;
|
||||
|
||||
//various graphics
|
||||
|
@ -23,13 +23,33 @@ int IFont::getScalingFactor() const
|
||||
return GH.screenHandler().getScalingFactor();
|
||||
}
|
||||
|
||||
size_t IFont::getLineHeight() const
|
||||
{
|
||||
return getLineHeightScaled() / getScalingFactor();
|
||||
}
|
||||
|
||||
size_t IFont::getGlyphWidth(const char * data) const
|
||||
{
|
||||
return getGlyphWidthScaled(data) / getScalingFactor();
|
||||
}
|
||||
|
||||
size_t IFont::getStringWidth(const std::string & data) const
|
||||
{
|
||||
return getStringWidthScaled(data) / getScalingFactor();
|
||||
}
|
||||
|
||||
size_t IFont::getFontAscent() const
|
||||
{
|
||||
return getFontAscentScaled() / getScalingFactor();
|
||||
}
|
||||
|
||||
size_t IFont::getStringWidthScaled(const std::string & data) const
|
||||
{
|
||||
size_t width = 0;
|
||||
|
||||
for(size_t i=0; i<data.size(); i += TextOperations::getUnicodeCharacterSize(data[i]))
|
||||
{
|
||||
width += getGlyphWidth(data.data() + i);
|
||||
width += getGlyphWidthScaled(data.data() + i);
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
@ -19,8 +19,6 @@ struct SDL_Surface;
|
||||
class IFont : boost::noncopyable
|
||||
{
|
||||
protected:
|
||||
/// Internal function to render font, see renderTextLeft
|
||||
virtual void renderText(SDL_Surface * surface, const std::string & data, const ColorRGBA & color, const Point & pos) const = 0;
|
||||
|
||||
int getScalingFactor() const;
|
||||
|
||||
@ -29,11 +27,27 @@ public:
|
||||
{}
|
||||
|
||||
/// Returns height of font
|
||||
virtual size_t getLineHeight() const = 0;
|
||||
virtual size_t getLineHeightScaled() const = 0;
|
||||
/// Returns width, in pixels of a character glyph. Pointer must contain at least characterSize valid bytes
|
||||
virtual size_t getGlyphWidth(const char * data) const = 0;
|
||||
virtual size_t getGlyphWidthScaled(const char * data) const = 0;
|
||||
/// Return width of the string
|
||||
virtual size_t getStringWidth(const std::string & data) const;
|
||||
virtual size_t getStringWidthScaled(const std::string & data) const;
|
||||
/// Returns distance from top of the font glyphs to baseline
|
||||
virtual size_t getFontAscentScaled() const = 0;
|
||||
|
||||
/// Returns height of font
|
||||
size_t getLineHeight() const;
|
||||
/// Returns width, in pixels of a character glyph. Pointer must contain at least characterSize valid bytes
|
||||
size_t getGlyphWidth(const char * data) const;
|
||||
/// Return width of the string
|
||||
size_t getStringWidth(const std::string & data) const;
|
||||
/// Returns distance from top of the font glyphs to baseline
|
||||
size_t getFontAscent() const;
|
||||
|
||||
/// Internal function to render font, see renderTextLeft
|
||||
virtual void renderText(SDL_Surface * surface, const std::string & data, const ColorRGBA & color, const Point & pos) const = 0;
|
||||
|
||||
virtual bool canRepresentCharacter(const char * data) const = 0;
|
||||
|
||||
/**
|
||||
* @param surface - destination to print text on
|
||||
|
@ -17,9 +17,11 @@ VCMI_LIB_NAMESPACE_END
|
||||
|
||||
struct SDL_Surface;
|
||||
|
||||
class IFont;
|
||||
class IImage;
|
||||
class CAnimation;
|
||||
enum class EImageBlitMode : uint8_t;
|
||||
enum EFonts : int8_t;
|
||||
|
||||
class IRenderHandler : public boost::noncopyable
|
||||
{
|
||||
@ -40,4 +42,7 @@ public:
|
||||
|
||||
/// Loads animation using given path
|
||||
virtual std::shared_ptr<CAnimation> loadAnimation(const AnimationPath & path, EImageBlitMode mode) = 0;
|
||||
|
||||
/// Returns font with specified identifer
|
||||
virtual std::shared_ptr<const IFont> loadFont(EFonts font) = 0;
|
||||
};
|
||||
|
@ -96,21 +96,14 @@ static AtlasLayout doAtlasPacking(const std::map<int, Point> & images)
|
||||
}
|
||||
}
|
||||
|
||||
void CBitmapFont::loadModFont(const std::string & modName, const ResourcePath & resource, std::unordered_map<CodePoint, EntryFNT> & loadedChars)
|
||||
void CBitmapFont::loadFont(const ResourcePath & resource, std::unordered_map<CodePoint, EntryFNT> & loadedChars)
|
||||
{
|
||||
if (!CResourceHandler::get(modName)->existsResource(resource))
|
||||
{
|
||||
logGlobal->error("Failed to load font %s from mod %s", resource.getName(), modName);
|
||||
return;
|
||||
}
|
||||
|
||||
auto data = CResourceHandler::get(modName)->load(resource)->readAll();
|
||||
std::string modLanguage = CGI->modh->getModLanguage(modName);
|
||||
auto data = CResourceHandler::get()->load(resource)->readAll();
|
||||
std::string modName = VLC->modh->findResourceOrigin(resource);
|
||||
std::string modLanguage = VLC->modh->getModLanguage(modName);
|
||||
std::string modEncoding = Languages::getLanguageOptions(modLanguage).encoding;
|
||||
|
||||
uint32_t dataHeight = data.first[5];
|
||||
|
||||
maxHeight = std::max(maxHeight, dataHeight);
|
||||
height = data.first[5];
|
||||
|
||||
constexpr size_t symbolsInFile = 0x100;
|
||||
constexpr size_t baseIndex = 32;
|
||||
@ -126,10 +119,10 @@ void CBitmapFont::loadModFont(const std::string & modName, const ResourcePath &
|
||||
symbol.leftOffset = read_le_u32(data.first.get() + baseIndex + charIndex * 12 + 0);
|
||||
symbol.width = read_le_u32(data.first.get() + baseIndex + charIndex * 12 + 4);
|
||||
symbol.rightOffset = read_le_u32(data.first.get() + baseIndex + charIndex * 12 + 8);
|
||||
symbol.height = dataHeight;
|
||||
symbol.height = height;
|
||||
|
||||
uint32_t pixelDataOffset = read_le_u32(data.first.get() + offsetIndex + charIndex * 4);
|
||||
uint32_t pixelsCount = dataHeight * symbol.width;
|
||||
uint32_t pixelsCount = height * symbol.width;
|
||||
|
||||
symbol.pixels.resize(pixelsCount);
|
||||
|
||||
@ -139,21 +132,27 @@ void CBitmapFont::loadModFont(const std::string & modName, const ResourcePath &
|
||||
|
||||
loadedChars[codepoint] = symbol;
|
||||
}
|
||||
|
||||
// Try to use symbol 'L' to detect font 'ascent' - number of pixels above text baseline
|
||||
const auto & symbolL = loadedChars['L'];
|
||||
uint32_t lastNonEmptyRow = 0;
|
||||
for (uint32_t row = 0; row < symbolL.height; ++row)
|
||||
{
|
||||
for (uint32_t col = 0; col < symbolL.width; ++col)
|
||||
if (symbolL.pixels.at(row * symbolL.width + col) == 255)
|
||||
lastNonEmptyRow = std::max(lastNonEmptyRow, row);
|
||||
}
|
||||
|
||||
ascent = lastNonEmptyRow + 1;
|
||||
}
|
||||
|
||||
CBitmapFont::CBitmapFont(const std::string & filename):
|
||||
maxHeight(0)
|
||||
height(0)
|
||||
{
|
||||
ResourcePath resource("data/" + filename, EResType::BMP_FONT);
|
||||
|
||||
std::unordered_map<CodePoint, EntryFNT> loadedChars;
|
||||
loadModFont("core", resource, loadedChars);
|
||||
|
||||
for(const auto & modName : VLC->modh->getActiveMods())
|
||||
{
|
||||
if (CResourceHandler::get(modName)->existsResource(resource))
|
||||
loadModFont(modName, resource, loadedChars);
|
||||
}
|
||||
loadFont(resource, loadedChars);
|
||||
|
||||
std::map<int, Point> atlasSymbol;
|
||||
for (auto const & symbol : loadedChars)
|
||||
@ -213,8 +212,6 @@ CBitmapFont::CBitmapFont(const std::string & filename):
|
||||
SDL_FreeSurface(atlasImage);
|
||||
atlasImage = scaledSurface;
|
||||
}
|
||||
|
||||
IMG_SavePNG(atlasImage, ("/home/ivan/font_" + filename).c_str());
|
||||
}
|
||||
|
||||
CBitmapFont::~CBitmapFont()
|
||||
@ -222,12 +219,12 @@ CBitmapFont::~CBitmapFont()
|
||||
SDL_FreeSurface(atlasImage);
|
||||
}
|
||||
|
||||
size_t CBitmapFont::getLineHeight() const
|
||||
size_t CBitmapFont::getLineHeightScaled() const
|
||||
{
|
||||
return maxHeight;
|
||||
return height * getScalingFactor();
|
||||
}
|
||||
|
||||
size_t CBitmapFont::getGlyphWidth(const char * data) const
|
||||
size_t CBitmapFont::getGlyphWidthScaled(const char * data) const
|
||||
{
|
||||
CodePoint localChar = TextOperations::getUnicodeCodepoint(data, 4);
|
||||
|
||||
@ -236,7 +233,12 @@ size_t CBitmapFont::getGlyphWidth(const char * data) const
|
||||
if (iter == chars.end())
|
||||
return 0;
|
||||
|
||||
return iter->second.leftOffset + iter->second.positionInAtlas.w + iter->second.rightOffset;
|
||||
return (iter->second.leftOffset + iter->second.positionInAtlas.w + iter->second.rightOffset) * getScalingFactor();
|
||||
}
|
||||
|
||||
size_t CBitmapFont::getFontAscentScaled() const
|
||||
{
|
||||
return ascent * getScalingFactor();
|
||||
}
|
||||
|
||||
bool CBitmapFont::canRepresentCharacter(const char *data) const
|
||||
|
@ -40,9 +40,10 @@ class CBitmapFont final : public IFont
|
||||
};
|
||||
|
||||
std::unordered_map<CodePoint, BitmapChar> chars;
|
||||
uint32_t maxHeight;
|
||||
uint32_t height;
|
||||
uint32_t ascent;
|
||||
|
||||
void loadModFont(const std::string & modName, const ResourcePath & resource, std::unordered_map<CodePoint, EntryFNT> & loadedChars);
|
||||
void loadFont(const ResourcePath & resource, std::unordered_map<CodePoint, EntryFNT> & loadedChars);
|
||||
|
||||
void renderCharacter(SDL_Surface * surface, const BitmapChar & character, const ColorRGBA & color, int &posX, int &posY) const;
|
||||
void renderText(SDL_Surface * surface, const std::string & data, const ColorRGBA & color, const Point & pos) const override;
|
||||
@ -50,11 +51,12 @@ public:
|
||||
explicit CBitmapFont(const std::string & filename);
|
||||
~CBitmapFont();
|
||||
|
||||
size_t getLineHeight() const override;
|
||||
size_t getGlyphWidth(const char * data) const override;
|
||||
size_t getFontAscentScaled() const override;
|
||||
size_t getLineHeightScaled() const override;
|
||||
size_t getGlyphWidthScaled(const char * data) const override;
|
||||
|
||||
/// returns true if this font contains provided utf-8 character
|
||||
bool canRepresentCharacter(const char * data) const;
|
||||
bool canRepresentCharacter(const char * data) const override;
|
||||
bool canRepresentString(const std::string & data) const;
|
||||
|
||||
friend class CBitmapHanFont;
|
||||
|
@ -1,127 +0,0 @@
|
||||
/*
|
||||
* CBitmapHanFont.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "CBitmapHanFont.h"
|
||||
|
||||
#include "CBitmapFont.h"
|
||||
#include "SDL_Extensions.h"
|
||||
|
||||
#include "../../lib/filesystem/Filesystem.h"
|
||||
#include "../../lib/json/JsonNode.h"
|
||||
#include "../../lib/Rect.h"
|
||||
#include "../../lib/texts/TextOperations.h"
|
||||
|
||||
#include <SDL_surface.h>
|
||||
|
||||
size_t CBitmapHanFont::getCharacterDataOffset(size_t index) const
|
||||
{
|
||||
size_t rowSize = (size + 7) / 8; // 1 bit per pixel, rounded up
|
||||
size_t charSize = rowSize * size; // glyph contains "size" rows
|
||||
return index * charSize;
|
||||
}
|
||||
|
||||
size_t CBitmapHanFont::getCharacterIndex(ui8 first, ui8 second) const
|
||||
{
|
||||
if (second > 0x7f )
|
||||
second--;
|
||||
|
||||
return (first - 0x81) * (12*16 - 2) + (second - 0x40);
|
||||
}
|
||||
|
||||
void CBitmapHanFont::renderCharacter(SDL_Surface * surface, int characterIndex, const ColorRGBA & color, int &posX, int &posY) const
|
||||
{
|
||||
//TODO: somewhat duplicated with CBitmapFont::renderCharacter();
|
||||
Rect clipRect;
|
||||
CSDL_Ext::getClipRect(surface, clipRect);
|
||||
|
||||
CSDL_Ext::TColorPutter colorPutter = CSDL_Ext::getPutterFor(surface);
|
||||
uint8_t bpp = surface->format->BytesPerPixel;
|
||||
|
||||
// start of line, may differ from 0 due to end of surface or clipped surface
|
||||
int lineBegin = std::max<int>(0, clipRect.y - posY);
|
||||
int lineEnd = std::min((int)size, clipRect.y + clipRect.h - posY);
|
||||
|
||||
// start end end of each row, may differ from 0
|
||||
int rowBegin = std::max<int>(0, clipRect.x - posX);
|
||||
int rowEnd = std::min<int>((int)size, clipRect.x + clipRect.w - posX);
|
||||
|
||||
//for each line in symbol
|
||||
for(int dy = lineBegin; dy <lineEnd; dy++)
|
||||
{
|
||||
uint8_t *dstLine = (uint8_t*)surface->pixels;
|
||||
uint8_t *source = data.first.get() + getCharacterDataOffset(characterIndex);
|
||||
|
||||
// shift source\destination pixels to current position
|
||||
dstLine += (posY+dy) * surface->pitch + posX * bpp;
|
||||
source += ((size + 7) / 8) * dy;
|
||||
|
||||
//for each column in line
|
||||
for(int dx = rowBegin; dx < rowEnd; dx++)
|
||||
{
|
||||
// select current bit in bitmap
|
||||
int bit = (source[dx / 8] << (dx % 8)) & 0x80;
|
||||
|
||||
uint8_t* dstPixel = dstLine + dx*bpp;
|
||||
if (bit != 0)
|
||||
colorPutter(dstPixel, color.r, color.g, color.b);
|
||||
}
|
||||
}
|
||||
posX += (int)size + 1;
|
||||
}
|
||||
|
||||
void CBitmapHanFont::renderText(SDL_Surface * surface, const std::string & data, const ColorRGBA & color, const Point & pos) const
|
||||
{
|
||||
int posX = pos.x;
|
||||
int posY = pos.y;
|
||||
|
||||
SDL_LockSurface(surface);
|
||||
|
||||
for(size_t i=0; i<data.size(); i += TextOperations::getUnicodeCharacterSize(data[i]))
|
||||
{
|
||||
std::string localChar = TextOperations::fromUnicode(data.substr(i, TextOperations::getUnicodeCharacterSize(data[i])), "GBK");
|
||||
|
||||
if (localChar.size() == 1)
|
||||
fallback->renderCharacter(surface, fallback->chars[ui8(localChar[0])], color, posX, posY);
|
||||
|
||||
if (localChar.size() == 2)
|
||||
renderCharacter(surface, (int)getCharacterIndex(localChar[0], localChar[1]), color, posX, posY);
|
||||
}
|
||||
SDL_UnlockSurface(surface);
|
||||
}
|
||||
|
||||
CBitmapHanFont::CBitmapHanFont(const JsonNode &config):
|
||||
fallback(new CBitmapFont(config["fallback"].String())),
|
||||
data(CResourceHandler::get()->load(ResourcePath("data/" + config["name"].String(), EResType::OTHER))->readAll()),
|
||||
size((size_t)config["size"].Float())
|
||||
{
|
||||
// basic tests to make sure that fonts are OK
|
||||
// 1) fonts must contain 190 "sections", 126 symbols each.
|
||||
assert(getCharacterIndex(0xfe, 0xff) == 190*126);
|
||||
// 2) ensure that font size is correct - enough to fit all possible symbols
|
||||
assert(getCharacterDataOffset(getCharacterIndex(0xfe, 0xff)) == data.second);
|
||||
}
|
||||
|
||||
size_t CBitmapHanFont::getLineHeight() const
|
||||
{
|
||||
return std::max(size + 1, fallback->getLineHeight());
|
||||
}
|
||||
|
||||
size_t CBitmapHanFont::getGlyphWidth(const char * data) const
|
||||
{
|
||||
std::string localChar = TextOperations::fromUnicode(std::string(data, TextOperations::getUnicodeCharacterSize(data[0])), "GBK");
|
||||
|
||||
if (localChar.size() == 1)
|
||||
return fallback->getGlyphWidth(data);
|
||||
|
||||
if (localChar.size() == 2)
|
||||
return size + 1;
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* CBitmapHanFont.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../render/IFont.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
class JsonNode;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class CBitmapFont;
|
||||
|
||||
/// supports multi-byte characters for such languages like Chinese
|
||||
class CBitmapHanFont final : public IFont
|
||||
{
|
||||
std::unique_ptr<CBitmapFont> fallback;
|
||||
// data, directly copied from file
|
||||
const std::pair<std::unique_ptr<ui8[]>, ui64> data;
|
||||
|
||||
// size of the font. Not available in file but needed for proper rendering
|
||||
const size_t size;
|
||||
|
||||
size_t getCharacterDataOffset(size_t index) const;
|
||||
size_t getCharacterIndex(ui8 first, ui8 second) const;
|
||||
|
||||
void renderCharacter(SDL_Surface * surface, int characterIndex, const ColorRGBA & color, int &posX, int &posY) const;
|
||||
void renderText(SDL_Surface * surface, const std::string & data, const ColorRGBA & color, const Point & pos) const override;
|
||||
public:
|
||||
CBitmapHanFont(const JsonNode & config);
|
||||
|
||||
size_t getLineHeight() const override;
|
||||
size_t getGlyphWidth(const char * data) const override;
|
||||
};
|
@ -15,6 +15,7 @@
|
||||
#include "../render/Colors.h"
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/json/JsonNode.h"
|
||||
#include "../../lib/filesystem/Filesystem.h"
|
||||
#include "../../lib/texts/TextOperations.h"
|
||||
@ -29,12 +30,13 @@ std::pair<std::unique_ptr<ui8[]>, ui64> CTrueTypeFont::loadData(const JsonNode &
|
||||
|
||||
int CTrueTypeFont::getPointSize(const JsonNode & config) const
|
||||
{
|
||||
float fontScale = settings["video"]["fontScalingFactor"].Float();
|
||||
int scalingFactor = getScalingFactor();
|
||||
|
||||
if (config.isNumber())
|
||||
return config.Integer() * scalingFactor;
|
||||
return std::round(config.Integer() * scalingFactor * fontScale);
|
||||
else
|
||||
return config[scalingFactor-1].Integer();
|
||||
return std::round(config[scalingFactor-1].Integer() * fontScale);
|
||||
}
|
||||
|
||||
TTF_Font * CTrueTypeFont::loadFont(const JsonNode &config)
|
||||
@ -62,57 +64,65 @@ int CTrueTypeFont::getFontStyle(const JsonNode &config) const
|
||||
CTrueTypeFont::CTrueTypeFont(const JsonNode & fontConfig):
|
||||
data(loadData(fontConfig)),
|
||||
font(loadFont(fontConfig), TTF_CloseFont),
|
||||
dropShadow(fontConfig["blend"].Bool()),
|
||||
blended(fontConfig["blend"].Bool())
|
||||
dropShadow(!fontConfig["noShadow"].Bool()),
|
||||
outline(fontConfig["outline"].Bool()),
|
||||
blended(true)
|
||||
{
|
||||
assert(font);
|
||||
|
||||
TTF_SetFontStyle(font.get(), getFontStyle(fontConfig));
|
||||
TTF_SetFontHinting(font.get(),TTF_HINTING_MONO);
|
||||
|
||||
std::string fallbackName = fontConfig["fallback"].String();
|
||||
|
||||
if (!fallbackName.empty())
|
||||
fallbackFont = std::make_unique<CBitmapFont>(fallbackName);
|
||||
}
|
||||
|
||||
CTrueTypeFont::~CTrueTypeFont() = default;
|
||||
|
||||
size_t CTrueTypeFont::getLineHeight() const
|
||||
size_t CTrueTypeFont::getFontAscentScaled() const
|
||||
{
|
||||
if (fallbackFont)
|
||||
return fallbackFont->getLineHeight();
|
||||
|
||||
return TTF_FontHeight(font.get()) / getScalingFactor();
|
||||
return TTF_FontAscent(font.get());
|
||||
}
|
||||
|
||||
size_t CTrueTypeFont::getGlyphWidth(const char *data) const
|
||||
size_t CTrueTypeFont::getLineHeightScaled() const
|
||||
{
|
||||
if (fallbackFont && fallbackFont->canRepresentCharacter(data))
|
||||
return fallbackFont->getGlyphWidth(data);
|
||||
|
||||
return getStringWidth(std::string(data, TextOperations::getUnicodeCharacterSize(*data)));
|
||||
return TTF_FontHeight(font.get());
|
||||
}
|
||||
|
||||
size_t CTrueTypeFont::getStringWidth(const std::string & data) const
|
||||
size_t CTrueTypeFont::getGlyphWidthScaled(const char *data) const
|
||||
{
|
||||
if (fallbackFont && fallbackFont->canRepresentString(data))
|
||||
return fallbackFont->getStringWidth(data);
|
||||
return getStringWidthScaled(std::string(data, TextOperations::getUnicodeCharacterSize(*data)));
|
||||
}
|
||||
|
||||
bool CTrueTypeFont::canRepresentCharacter(const char * data) const
|
||||
{
|
||||
uint32_t codepoint = TextOperations::getUnicodeCodepoint(data, TextOperations::getUnicodeCharacterSize(*data));
|
||||
#if SDL_TTF_VERSION_ATLEAST(2, 0, 18)
|
||||
return TTF_GlyphIsProvided32(font.get(), codepoint);
|
||||
#elif SDL_TTF_VERSION_ATLEAST(2, 0, 12)
|
||||
if (codepoint <= 0xffff)
|
||||
return TTF_GlyphIsProvided(font.get(), codepoint);
|
||||
return true;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t CTrueTypeFont::getStringWidthScaled(const std::string & data) const
|
||||
{
|
||||
int width;
|
||||
TTF_SizeUTF8(font.get(), data.c_str(), &width, nullptr);
|
||||
return width / getScalingFactor();
|
||||
return width;
|
||||
}
|
||||
|
||||
void CTrueTypeFont::renderText(SDL_Surface * surface, const std::string & data, const ColorRGBA & color, const Point & pos) const
|
||||
{
|
||||
if (fallbackFont && fallbackFont->canRepresentString(data))
|
||||
if (color.r != 0 && color.g != 0 && color.b != 0) // not black - add shadow
|
||||
{
|
||||
fallbackFont->renderText(surface, data, color, pos);
|
||||
return;
|
||||
}
|
||||
if (outline)
|
||||
renderText(surface, data, Colors::BLACK, pos - Point(1,1) * getScalingFactor());
|
||||
|
||||
if (dropShadow && color.r != 0 && color.g != 0 && color.b != 0) // not black - add shadow
|
||||
renderText(surface, data, Colors::BLACK, pos + Point(1,1) * getScalingFactor());
|
||||
if (dropShadow || outline)
|
||||
renderText(surface, data, Colors::BLACK, pos + Point(1,1) * getScalingFactor());
|
||||
}
|
||||
|
||||
if (!data.empty())
|
||||
{
|
||||
|
@ -21,11 +21,11 @@ using TTF_Font = struct _TTF_Font;
|
||||
|
||||
class CTrueTypeFont final : public IFont
|
||||
{
|
||||
std::unique_ptr<CBitmapFont> fallbackFont;
|
||||
const std::pair<std::unique_ptr<ui8[]>, ui64> data;
|
||||
|
||||
const std::unique_ptr<TTF_Font, void (*)(TTF_Font*)> font;
|
||||
const bool blended;
|
||||
const bool outline;
|
||||
const bool dropShadow;
|
||||
|
||||
std::pair<std::unique_ptr<ui8[]>, ui64> loadData(const JsonNode & config);
|
||||
@ -34,11 +34,14 @@ class CTrueTypeFont final : public IFont
|
||||
int getFontStyle(const JsonNode & config) const;
|
||||
|
||||
void renderText(SDL_Surface * surface, const std::string & data, const ColorRGBA & color, const Point & pos) const override;
|
||||
size_t getFontAscentScaled() const override;
|
||||
public:
|
||||
CTrueTypeFont(const JsonNode & fontConfig);
|
||||
~CTrueTypeFont();
|
||||
|
||||
size_t getLineHeight() const override;
|
||||
size_t getGlyphWidth(const char * data) const override;
|
||||
size_t getStringWidth(const std::string & data) const override;
|
||||
bool canRepresentCharacter(const char * data) const override;
|
||||
|
||||
size_t getLineHeightScaled() const override;
|
||||
size_t getGlyphWidthScaled(const char * data) const override;
|
||||
size_t getStringWidthScaled(const std::string & data) const override;
|
||||
};
|
||||
|
136
client/renderSDL/FontChain.cpp
Normal file
136
client/renderSDL/FontChain.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* FontChain.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "FontChain.h"
|
||||
|
||||
#include "CTrueTypeFont.h"
|
||||
#include "CBitmapFont.h"
|
||||
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/texts/TextOperations.h"
|
||||
|
||||
void FontChain::renderText(SDL_Surface * surface, const std::string & data, const ColorRGBA & color, const Point & pos) const
|
||||
{
|
||||
auto chunks = splitTextToChunks(data);
|
||||
int maxAscent = getFontAscentScaled();
|
||||
Point currentPos = pos;
|
||||
for (auto const & chunk : chunks)
|
||||
{
|
||||
Point chunkPos = currentPos;
|
||||
int currAscent = chunk.font->getFontAscentScaled();
|
||||
chunkPos.y += maxAscent - currAscent;
|
||||
chunk.font->renderText(surface, chunk.text, color, chunkPos);
|
||||
currentPos.x += chunk.font->getStringWidthScaled(chunk.text);
|
||||
}
|
||||
}
|
||||
|
||||
size_t FontChain::getFontAscentScaled() const
|
||||
{
|
||||
size_t maxHeight = 0;
|
||||
for(const auto & font : chain)
|
||||
maxHeight = std::max(maxHeight, font->getFontAscentScaled());
|
||||
return maxHeight;
|
||||
}
|
||||
|
||||
bool FontChain::bitmapFontsPrioritized() const
|
||||
{
|
||||
const std::string & fontType = settings["video"]["fontsType"].String();
|
||||
if (fontType == "original")
|
||||
return true;
|
||||
if (fontType == "scalable")
|
||||
return false;
|
||||
|
||||
// else - autoselection.
|
||||
|
||||
if (getScalingFactor() != 1)
|
||||
return false; // If xbrz in use ttf/scalable fonts are preferred
|
||||
|
||||
if (!vstd::isAlmostEqual(1.0, settings["video"]["fontScalingFactor"].Float()))
|
||||
return false; // If player requested non-100% scaling - use scalable fonts
|
||||
|
||||
return true; // else - use original bitmap fonts
|
||||
}
|
||||
|
||||
void FontChain::addTrueTypeFont(const JsonNode & trueTypeConfig)
|
||||
{
|
||||
chain.insert(chain.begin(), std::make_unique<CTrueTypeFont>(trueTypeConfig));
|
||||
}
|
||||
|
||||
void FontChain::addBitmapFont(const std::string & bitmapFilename)
|
||||
{
|
||||
if (bitmapFontsPrioritized())
|
||||
chain.insert(chain.begin(), std::make_unique<CBitmapFont>(bitmapFilename));
|
||||
else
|
||||
chain.push_back(std::make_unique<CBitmapFont>(bitmapFilename));
|
||||
}
|
||||
|
||||
bool FontChain::canRepresentCharacter(const char * data) const
|
||||
{
|
||||
for(const auto & font : chain)
|
||||
if (font->canRepresentCharacter(data))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t FontChain::getLineHeightScaled() const
|
||||
{
|
||||
size_t maxHeight = 0;
|
||||
for(const auto & font : chain)
|
||||
maxHeight = std::max(maxHeight, font->getLineHeightScaled());
|
||||
return maxHeight;
|
||||
}
|
||||
|
||||
size_t FontChain::getGlyphWidthScaled(const char * data) const
|
||||
{
|
||||
for(const auto & font : chain)
|
||||
if (font->canRepresentCharacter(data))
|
||||
return font->getGlyphWidthScaled(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<FontChain::TextChunk> FontChain::splitTextToChunks(const std::string & data) const
|
||||
{
|
||||
std::vector<TextChunk> chunks;
|
||||
|
||||
for (size_t i = 0; i < data.size(); i += TextOperations::getUnicodeCharacterSize(data[i]))
|
||||
{
|
||||
const IFont * currentFont = nullptr;
|
||||
for(const auto & font : chain)
|
||||
{
|
||||
if (font->canRepresentCharacter(data.data() + i))
|
||||
{
|
||||
currentFont = font.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentFont == nullptr)
|
||||
continue; // not representable
|
||||
|
||||
std::string symbol = data.substr(i, TextOperations::getUnicodeCharacterSize(data[i]));
|
||||
|
||||
if (chunks.empty() || chunks.back().font != currentFont)
|
||||
chunks.push_back({currentFont, symbol});
|
||||
else
|
||||
chunks.back().text += symbol;
|
||||
}
|
||||
|
||||
return chunks;
|
||||
}
|
||||
|
||||
size_t FontChain::getStringWidthScaled(const std::string & data) const
|
||||
{
|
||||
size_t result = 0;
|
||||
auto chunks = splitTextToChunks(data);
|
||||
for (auto const & chunk : chunks)
|
||||
result += chunk.font->getStringWidthScaled(chunk.text);
|
||||
|
||||
return result;
|
||||
}
|
43
client/renderSDL/FontChain.h
Normal file
43
client/renderSDL/FontChain.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* FontChain.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../render/IFont.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
class JsonNode;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class FontChain final : public IFont
|
||||
{
|
||||
struct TextChunk
|
||||
{
|
||||
const IFont * font;
|
||||
std::string text;
|
||||
};
|
||||
|
||||
std::vector<TextChunk> splitTextToChunks(const std::string & data) const;
|
||||
|
||||
std::vector<std::unique_ptr<IFont>> chain;
|
||||
|
||||
void renderText(SDL_Surface * surface, const std::string & data, const ColorRGBA & color, const Point & pos) const override;
|
||||
size_t getFontAscentScaled() const override;
|
||||
bool bitmapFontsPrioritized() const;
|
||||
public:
|
||||
FontChain() = default;
|
||||
|
||||
void addTrueTypeFont(const JsonNode & trueTypeConfig);
|
||||
void addBitmapFont(const std::string & bitmapFilename);
|
||||
|
||||
size_t getLineHeightScaled() const override;
|
||||
size_t getGlyphWidthScaled(const char * data) const override;
|
||||
size_t getStringWidthScaled(const std::string & data) const override;
|
||||
bool canRepresentCharacter(const char * data) const override;
|
||||
};
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "SDLImage.h"
|
||||
#include "ImageScaled.h"
|
||||
#include "FontChain.h"
|
||||
|
||||
#include "../gui/CGuiHandler.h"
|
||||
|
||||
@ -20,7 +21,6 @@
|
||||
#include "../render/Colors.h"
|
||||
#include "../render/ColorFilter.h"
|
||||
#include "../render/IScreenHandler.h"
|
||||
|
||||
#include "../../lib/json/JsonUtils.h"
|
||||
#include "../../lib/filesystem/Filesystem.h"
|
||||
#include "../../lib/VCMIDirs.h"
|
||||
@ -335,3 +335,32 @@ void RenderHandler::onLibraryLoadingFinished(const Services * services)
|
||||
addImageListEntries(services->spells());
|
||||
addImageListEntries(services->skills());
|
||||
}
|
||||
|
||||
std::shared_ptr<const IFont> RenderHandler::loadFont(EFonts font)
|
||||
{
|
||||
if (fonts.count(font))
|
||||
return fonts.at(font);
|
||||
|
||||
const int8_t index = static_cast<int8_t>(font);
|
||||
auto configList = CResourceHandler::get()->getResourcesWithName(JsonPath::builtin("config/fonts.json"));
|
||||
std::shared_ptr<FontChain> loadedFont = std::make_shared<FontChain>();
|
||||
std::string bitmapPath;
|
||||
|
||||
for(auto & loader : configList)
|
||||
{
|
||||
auto stream = loader->load(JsonPath::builtin("config/fonts.json"));
|
||||
std::unique_ptr<ui8[]> textData(new ui8[stream->getSize()]);
|
||||
stream->read(textData.get(), stream->getSize());
|
||||
const JsonNode config(reinterpret_cast<const std::byte*>(textData.get()), stream->getSize(), "config/fonts.json");
|
||||
const JsonVector & bmpConf = config["bitmap"].Vector();
|
||||
const JsonNode & ttfConf = config["trueType"];
|
||||
|
||||
bitmapPath = bmpConf[index].String();
|
||||
if (!ttfConf[bitmapPath].isNull())
|
||||
loadedFont->addTrueTypeFont(ttfConf[bitmapPath]);
|
||||
}
|
||||
loadedFont->addBitmapFont(bitmapPath);
|
||||
|
||||
fonts[font] = loadedFont;
|
||||
return loadedFont;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ class RenderHandler : public IRenderHandler
|
||||
std::map<AnimationPath, std::shared_ptr<CDefFile>> animationFiles;
|
||||
std::map<AnimationPath, AnimationLayoutMap> animationLayouts;
|
||||
std::map<ImageLocator, std::shared_ptr<ISharedImage>> imageFiles;
|
||||
std::map<EFonts, std::shared_ptr<const IFont>> fonts;
|
||||
|
||||
std::shared_ptr<CDefFile> getAnimationFile(const AnimationPath & path);
|
||||
AnimationLayoutMap & getAnimationLayout(const AnimationPath & path);
|
||||
@ -59,4 +60,7 @@ public:
|
||||
std::shared_ptr<CAnimation> loadAnimation(const AnimationPath & path, EImageBlitMode mode) override;
|
||||
|
||||
std::shared_ptr<IImage> createImage(SDL_Surface * source) override;
|
||||
|
||||
/// Returns font with specified identifer
|
||||
std::shared_ptr<const IFont> loadFont(EFonts font) override;
|
||||
};
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "../gui/Shortcut.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../render/IFont.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
#include "../render/Graphics.h"
|
||||
#include "../windows/CMessage.h"
|
||||
#include "../windows/InfoWindows.h"
|
||||
@ -95,9 +96,11 @@ void CComponent::init(ComponentType Type, ComponentSubType Subtype, std::optiona
|
||||
max = 80;
|
||||
|
||||
std::vector<std::string> textLines = CMessage::breakText(getSubtitle(), std::max<int>(max, pos.w), font);
|
||||
const auto & fontPtr = GH.renderHandler().loadFont(font);
|
||||
const int height = static_cast<int>(fontPtr->getLineHeight());
|
||||
|
||||
for(auto & line : textLines)
|
||||
{
|
||||
int height = static_cast<int>(graphics->fonts[font]->getLineHeight());
|
||||
auto label = std::make_shared<CLabel>(pos.w/2, pos.h + height/2, font, ETextAlignment::CENTER, Colors::WHITE, line);
|
||||
|
||||
pos.h += height;
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "../gui/Shortcut.h"
|
||||
#include "../render/Graphics.h"
|
||||
#include "../render/IFont.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
|
||||
#include "../../lib/texts/TextOperations.h"
|
||||
|
||||
@ -190,8 +191,9 @@ void CTextInput::updateLabel()
|
||||
std::string visibleText = getVisibleText();
|
||||
|
||||
label->alignment = originalAlignment;
|
||||
const auto & font = GH.renderHandler().loadFont(label->font);
|
||||
|
||||
while (graphics->fonts[label->font]->getStringWidth(visibleText) > pos.w)
|
||||
while (font->getStringWidth(visibleText) > pos.w)
|
||||
{
|
||||
label->alignment = ETextAlignment::CENTERRIGHT;
|
||||
visibleText = visibleText.substr(TextOperations::getUnicodeCharacterSize(visibleText[0]));
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "../render/Canvas.h"
|
||||
#include "../render/Graphics.h"
|
||||
#include "../render/IFont.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
|
||||
#include "../../lib/texts/TextOperations.h"
|
||||
|
||||
@ -56,8 +57,9 @@ CLabel::CLabel(int x, int y, EFonts Font, ETextAlignment Align, const ColorRGBA
|
||||
|
||||
if(alignment == ETextAlignment::TOPLEFT) // causes issues for MIDDLE
|
||||
{
|
||||
pos.w = (int)graphics->fonts[font]->getStringWidth(visibleText().c_str());
|
||||
pos.h = (int)graphics->fonts[font]->getLineHeight();
|
||||
const auto & fontPtr = GH.renderHandler().loadFont(font);
|
||||
pos.w = fontPtr->getStringWidth(visibleText().c_str());
|
||||
pos.h = fontPtr->getLineHeight();
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,8 +116,12 @@ void CLabel::setMaxWidth(int width)
|
||||
void CLabel::trimText()
|
||||
{
|
||||
if(maxWidth > 0)
|
||||
while ((int)graphics->fonts[font]->getStringWidth(visibleText().c_str()) > maxWidth)
|
||||
{
|
||||
const auto & fontPtr = GH.renderHandler().loadFont(font);
|
||||
|
||||
while (fontPtr->getStringWidth(visibleText().c_str()) > maxWidth)
|
||||
TextOperations::trimRightUnicode(text);
|
||||
}
|
||||
}
|
||||
|
||||
void CLabel::setColor(const ColorRGBA & Color)
|
||||
@ -132,7 +138,8 @@ void CLabel::setColor(const ColorRGBA & Color)
|
||||
|
||||
size_t CLabel::getWidth()
|
||||
{
|
||||
return graphics->fonts[font]->getStringWidth(visibleText());
|
||||
const auto & fontPtr = GH.renderHandler().loadFont(font);
|
||||
return fontPtr->getStringWidth(visibleText());
|
||||
}
|
||||
|
||||
CMultiLineLabel::CMultiLineLabel(Rect position, EFonts Font, ETextAlignment Align, const ColorRGBA & Color, const std::string & Text) :
|
||||
@ -171,7 +178,7 @@ void CMultiLineLabel::setText(const std::string & Txt)
|
||||
|
||||
void CTextContainer::blitLine(Canvas & to, Rect destRect, std::string what)
|
||||
{
|
||||
const auto f = graphics->fonts[font];
|
||||
const auto f = GH.renderHandler().loadFont(font);
|
||||
Point where = destRect.topLeft();
|
||||
const std::string delimiters = "{}";
|
||||
auto delimitersCount = std::count_if(what.cbegin(), what.cend(), [&delimiters](char c)
|
||||
@ -264,7 +271,7 @@ void CMultiLineLabel::showAll(Canvas & to)
|
||||
{
|
||||
CIntObject::showAll(to);
|
||||
|
||||
const auto f = graphics->fonts[font];
|
||||
const auto & fontPtr = GH.renderHandler().loadFont(font);
|
||||
|
||||
// calculate which lines should be visible
|
||||
int totalLines = static_cast<int>(lines.size());
|
||||
@ -274,17 +281,17 @@ void CMultiLineLabel::showAll(Canvas & to)
|
||||
if(beginLine < 0)
|
||||
beginLine = 0;
|
||||
else
|
||||
beginLine /= (int)f->getLineHeight();
|
||||
beginLine /= fontPtr->getLineHeight();
|
||||
|
||||
if(endLine < 0)
|
||||
endLine = 0;
|
||||
else
|
||||
endLine /= (int)f->getLineHeight();
|
||||
endLine /= fontPtr->getLineHeight();
|
||||
endLine++;
|
||||
|
||||
// and where they should be displayed
|
||||
Point lineStart = getTextLocation().topLeft() - visibleSize + Point(0, beginLine * (int)f->getLineHeight());
|
||||
Point lineSize = Point(getTextLocation().w, (int)f->getLineHeight());
|
||||
Point lineStart = getTextLocation().topLeft() - visibleSize + Point(0, beginLine * fontPtr->getLineHeight());
|
||||
Point lineSize = Point(getTextLocation().w, fontPtr->getLineHeight());
|
||||
|
||||
CSDL_Ext::CClipRectGuard guard(to.getInternalSurface(), getTextLocation()); // to properly trim text that is too big to fit
|
||||
|
||||
@ -293,7 +300,7 @@ void CMultiLineLabel::showAll(Canvas & to)
|
||||
if(!lines[i].empty()) //non-empty line
|
||||
blitLine(to, Rect(lineStart, lineSize), lines[i]);
|
||||
|
||||
lineStart.y += (int)f->getLineHeight();
|
||||
lineStart.y += fontPtr->getLineHeight();
|
||||
}
|
||||
}
|
||||
|
||||
@ -301,15 +308,15 @@ void CMultiLineLabel::splitText(const std::string & Txt, bool redrawAfter)
|
||||
{
|
||||
lines.clear();
|
||||
|
||||
const auto f = graphics->fonts[font];
|
||||
int lineHeight = static_cast<int>(f->getLineHeight());
|
||||
const auto & fontPtr = GH.renderHandler().loadFont(font);
|
||||
int lineHeight = static_cast<int>(fontPtr->getLineHeight());
|
||||
|
||||
lines = CMessage::breakText(Txt, pos.w, font);
|
||||
|
||||
textSize.y = lineHeight * (int)lines.size();
|
||||
textSize.x = 0;
|
||||
for(const std::string & line : lines)
|
||||
vstd::amax(textSize.x, f->getStringWidth(line.c_str()));
|
||||
vstd::amax(textSize.x, fontPtr->getStringWidth(line.c_str()));
|
||||
if(redrawAfter)
|
||||
redraw();
|
||||
}
|
||||
@ -322,7 +329,8 @@ Rect CMultiLineLabel::getTextLocation()
|
||||
if(pos.h <= textSize.y)
|
||||
return pos;
|
||||
|
||||
Point textSize(pos.w, (int)graphics->fonts[font]->getLineHeight() * (int)lines.size());
|
||||
const auto & fontPtr = GH.renderHandler().loadFont(font);
|
||||
Point textSize(pos.w, fontPtr->getLineHeight() * (int)lines.size());
|
||||
Point textOffset(pos.w - textSize.x, pos.h - textSize.y);
|
||||
|
||||
switch(alignment)
|
||||
@ -421,11 +429,12 @@ void CTextBox::setText(const std::string & text)
|
||||
label->pos.w = pos.w - 16;
|
||||
assert(label->pos.w > 0);
|
||||
label->setText(text);
|
||||
const auto & fontPtr = GH.renderHandler().loadFont(label->font);
|
||||
|
||||
OBJECT_CONSTRUCTION;
|
||||
slider = std::make_shared<CSlider>(Point(pos.w - 16, 0), pos.h, std::bind(&CTextBox::sliderMoved, this, _1),
|
||||
label->pos.h, label->textSize.y, 0, Orientation::VERTICAL, CSlider::EStyle(sliderStyle));
|
||||
slider->setScrollStep((int)graphics->fonts[label->font]->getLineHeight());
|
||||
slider->setScrollStep(fontPtr->getLineHeight());
|
||||
slider->setPanningStep(1);
|
||||
slider->setScrollBounds(pos - slider->pos.topLeft());
|
||||
}
|
||||
|
@ -70,6 +70,8 @@ std::vector<std::string> CMessage::breakText(std::string text, size_t maxLineWid
|
||||
|
||||
boost::algorithm::trim_right_if(text, boost::algorithm::is_any_of(std::string(" ")));
|
||||
|
||||
const auto & fontPtr = GH.renderHandler().loadFont(font);
|
||||
|
||||
// each iteration generates one output line
|
||||
while(text.length())
|
||||
{
|
||||
@ -83,7 +85,7 @@ std::vector<std::string> CMessage::breakText(std::string text, size_t maxLineWid
|
||||
std::string printableString;
|
||||
|
||||
// loops till line is full or end of text reached
|
||||
while(currPos < text.length() && text[currPos] != 0x0a && graphics->fonts[font]->getStringWidth(printableString) <= maxLineWidth)
|
||||
while(currPos < text.length() && text[currPos] != 0x0a && fontPtr->getStringWidth(printableString) <= maxLineWidth)
|
||||
{
|
||||
symbolSize = TextOperations::getUnicodeCharacterSize(text[currPos]);
|
||||
|
||||
@ -193,9 +195,9 @@ std::string CMessage::guessHeader(const std::string & msg)
|
||||
|
||||
int CMessage::guessHeight(const std::string & txt, int width, EFonts font)
|
||||
{
|
||||
const auto f = graphics->fonts[font];
|
||||
const auto & fontPtr = GH.renderHandler().loadFont(font);
|
||||
const auto lines = CMessage::breakText(txt, width, font);
|
||||
size_t lineHeight = f->getLineHeight();
|
||||
size_t lineHeight = fontPtr->getLineHeight();
|
||||
return lineHeight * lines.size();
|
||||
}
|
||||
|
||||
|
@ -5,12 +5,12 @@
|
||||
"bitmap" :
|
||||
[
|
||||
"BIGFONT", // Mostly used for window titles
|
||||
"CALLI10R", // Unused in VCMI
|
||||
"CREDITS", // Used for credits menu
|
||||
"HISCORE", // Unused in VCMI
|
||||
"CALLI10R", // Only in World View menu
|
||||
"CREDITS", // Only in Credits menu
|
||||
"HISCORE", // Only in High Scores menu
|
||||
"MEDFONT", // Some titles
|
||||
"SMALFONT", // Most of the messages
|
||||
"TIMES08R", // Used to display amounts on creature card
|
||||
"TIMES08R", // Unused in VCMI
|
||||
"TINY", // Some text
|
||||
"VERD10B" // Unused in VCMI
|
||||
],
|
||||
@ -25,17 +25,18 @@
|
||||
// b) list of scaling factors for each scaling mode, e.g. [ 10, 16, 22, 26]. In this case game will select point size according to xBRZ scaling factor
|
||||
// so unscaled mode will use 10px, xbrz2 will use 16px, and xbrz3 will use 22
|
||||
// "style" - italic and\or bold, indicates font style
|
||||
// "blend" - if set to true, font will be antialiased
|
||||
// "outline" - if set, black shadow will be generated around entire text (instead of only bottom-right side)
|
||||
// "noShadow" - if set, this font will not drop any shadow
|
||||
"trueType":
|
||||
{
|
||||
//"BIGFONT" : { "file" : "LiberationSerif-Bold.ttf", "size" : 22, "blend" : true},
|
||||
//"CALLI10R" : { "file" : "Georgia.ttf", "size" : 10},
|
||||
//"CREDITS" : { "file" : "LiberationSerif-Bold.ttf", "size" : 28},
|
||||
//"HISCORE" : { "file" : "Georgia.ttf", "size" : 13},
|
||||
//"MEDFONT" : { "file" : "LiberationSerif-Bold.ttf", "size" : 16}, // breaks messages (from map events)
|
||||
//"SMALFONT" : { "file" : "LiberationSerif-Regular.ttf", "size" : 13, "blend" : true},
|
||||
//"TIMES08R" : { "file" : "LiberationSerif-Regular.ttf", "size" : 11, "blend" : true},
|
||||
//"TINY" : { "file" : "LiberationSerif-Regular.ttf", "size" : 11, "blend" : true},
|
||||
//"VERD10B" : { "file" : "Georgia.ttf", "size" : 13}
|
||||
"BIGFONT" : { "file" : "NotoSerif-Bold.ttf", "size" : [ 19, 39, 58, 78] },
|
||||
"CALLI10R" : { "file" : "NotoSerif-Bold.ttf", "size" : [ 12, 24, 36, 48] }, // TODO: find better matching font? This is likely non-free 'Callisto MT' font
|
||||
"CREDITS" : { "file" : "NotoSerif-Black.ttf", "size" : [ 22, 44, 66, 88], "outline" : true },
|
||||
"HISCORE" : { "file" : "NotoSerif-Black.ttf", "size" : [ 18, 36, 54, 72], "outline" : true },
|
||||
"MEDFONT" : { "file" : "NotoSerif-Bold.ttf", "size" : [ 15, 31, 46, 62] },
|
||||
"SMALFONT" : { "file" : "NotoSerif-Medium.ttf", "size" : [ 12, 24, 36, 48] },
|
||||
"TIMES08R" : { "file" : "NotoSerif-Medium.ttf", "size" : [ 8, 16, 24, 32] },
|
||||
"TINY" : { "file" : "NotoSans-Medium.ttf", "size" : [ 9, 19, 28, 38], "noShadow" : true }, // The only H3 font without shadow
|
||||
"VERD10B" : { "file" : "NotoSans-Medium.ttf", "size" : [ 13, 26, 39, 52] }
|
||||
}
|
||||
}
|
||||
|
@ -166,6 +166,8 @@
|
||||
"showfps",
|
||||
"targetfps",
|
||||
"vsync",
|
||||
"fontsType",
|
||||
"fontScalingFactor",
|
||||
"upscalingFilter",
|
||||
"fontUpscalingFilter",
|
||||
"downscalingFilter"
|
||||
@ -232,6 +234,15 @@
|
||||
"type" : "boolean",
|
||||
"default" : true
|
||||
},
|
||||
"fontsType" : {
|
||||
"type" : "string",
|
||||
"enum" : [ "auto", "original", "scalable" ],
|
||||
"default" : "auto"
|
||||
},
|
||||
"fontScalingFactor" : {
|
||||
"type" : "number",
|
||||
"default" : 1
|
||||
},
|
||||
"fontUpscalingFilter" : {
|
||||
"type" : "string",
|
||||
"enum" : [ "nearest", "bilinear", "xbrz" ],
|
||||
|
@ -174,17 +174,13 @@ void CSettingsView::loadSettings()
|
||||
ui->sliderControllerSticksAcceleration->setValue(settings["input"]["controllerAxisScale"].Float() * 100);
|
||||
ui->lineEditGameLobbyHost->setText(QString::fromStdString(settings["lobby"]["hostname"].String()));
|
||||
ui->spinBoxNetworkPortLobby->setValue(settings["lobby"]["port"].Integer());
|
||||
|
||||
auto mainWindow = getMainWindow();
|
||||
if(mainWindow)
|
||||
{
|
||||
bool fontModAvailable = mainWindow->getModView()->isModInstalled("vcmi-extras.truetypefonts");
|
||||
if(!fontModAvailable)
|
||||
{
|
||||
ui->labelTtfFont->hide();
|
||||
ui->buttonTtfFont->hide();
|
||||
}
|
||||
}
|
||||
|
||||
if (settings["video"]["fontsType"].String() == "auto")
|
||||
ui->buttonFontAuto->setChecked(true);
|
||||
else if (settings["video"]["fontsType"].String() == "original")
|
||||
ui->buttonFontOriginal->setChecked(true);
|
||||
else
|
||||
ui->buttonFontScalable->setChecked(true);
|
||||
|
||||
loadToggleButtonSettings();
|
||||
}
|
||||
@ -210,9 +206,9 @@ void CSettingsView::loadToggleButtonSettings()
|
||||
int cursorTypeIndex = vstd::find_pos(cursorTypesList, cursorType);
|
||||
setCheckbuttonState(ui->buttonCursorType, cursorTypeIndex);
|
||||
|
||||
auto mainWindow = getMainWindow();
|
||||
if(mainWindow)
|
||||
setCheckbuttonState(ui->buttonTtfFont, mainWindow->getModView()->isModEnabled("vcmi-extras.truetypefonts"));
|
||||
int fontScalingPercentage = settings["video"]["fontScalingFactor"].Float() * 100;
|
||||
ui->sliderScalingFont->setValue(fontScalingPercentage / 5);
|
||||
|
||||
}
|
||||
|
||||
void CSettingsView::fillValidResolutions()
|
||||
@ -770,12 +766,28 @@ void CSettingsView::on_sliderControllerSticksSensitivity_valueChanged(int value)
|
||||
node->Integer() = value;
|
||||
}
|
||||
|
||||
void CSettingsView::on_buttonTtfFont_toggled(bool value)
|
||||
void CSettingsView::on_sliderScalingFont_valueChanged(int value)
|
||||
{
|
||||
auto mainWindow = getMainWindow();
|
||||
if(value)
|
||||
mainWindow->getModView()->enableModByName("vcmi-extras.truetypefonts");
|
||||
else
|
||||
mainWindow->getModView()->disableModByName("vcmi-extras.truetypefonts");
|
||||
updateCheckbuttonText(ui->buttonTtfFont);
|
||||
int actualValuePercentage = value * 5;
|
||||
ui->labelScalingFontValue->setText(QString("%1%").arg(actualValuePercentage));
|
||||
Settings node = settings.write["video"]["fontScalingFactor"];
|
||||
node->Float() = actualValuePercentage / 100.0;
|
||||
}
|
||||
|
||||
void CSettingsView::on_buttonFontAuto_clicked(bool checked)
|
||||
{
|
||||
Settings node = settings.write["video"]["fontsType"];
|
||||
node->String() = "auto";
|
||||
}
|
||||
|
||||
void CSettingsView::on_buttonFontScalable_clicked(bool checked)
|
||||
{
|
||||
Settings node = settings.write["video"]["fontsType"];
|
||||
node->String() = "scalable";
|
||||
}
|
||||
|
||||
void CSettingsView::on_buttonFontOriginal_clicked(bool checked)
|
||||
{
|
||||
Settings node = settings.write["video"]["fontsType"];
|
||||
node->String() = "original";
|
||||
}
|
||||
|
@ -88,7 +88,13 @@ private slots:
|
||||
|
||||
void on_sliderControllerSticksSensitivity_valueChanged(int value);
|
||||
|
||||
void on_buttonTtfFont_toggled(bool value);
|
||||
//void on_buttonTtfFont_toggled(bool value);
|
||||
|
||||
void on_sliderScalingFont_valueChanged(int value);
|
||||
|
||||
void on_buttonFontAuto_clicked(bool checked);
|
||||
void on_buttonFontScalable_clicked(bool checked);
|
||||
void on_buttonFontOriginal_clicked(bool checked);
|
||||
|
||||
private:
|
||||
Ui::CSettingsView * ui;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -102,7 +102,7 @@
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistmodel_moc.cpp" line="44"/>
|
||||
<source>Test</source>
|
||||
<translation>Testa</translation>
|
||||
<translation>Test</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistmodel_moc.cpp" line="45"/>
|
||||
@ -224,7 +224,7 @@
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.ui" line="86"/>
|
||||
<source>Active</source>
|
||||
<translation>Tillgångar</translation>
|
||||
<translation>Aktiv</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.ui" line="91"/>
|
||||
@ -290,7 +290,7 @@
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.ui" line="340"/>
|
||||
<source>Abort</source>
|
||||
<translation>Ge upp</translation>
|
||||
<translation>Avbryt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="289"/>
|
||||
@ -315,7 +315,7 @@
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="296"/>
|
||||
<source>Download size</source>
|
||||
<translation>Nedladdningsstorlek</translation>
|
||||
<translation>Nedladdnings-storlek</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="298"/>
|
||||
@ -346,7 +346,7 @@
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="321"/>
|
||||
<source>Supported VCMI version</source>
|
||||
<translation>Stödd VCMI-version</translation>
|
||||
<translation>VCMI-version som stöds</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="321"/>
|
||||
@ -357,7 +357,7 @@
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="193"/>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="824"/>
|
||||
<source>mods repository index</source>
|
||||
<translation>Modd-repositorie index</translation>
|
||||
<translation>Modd-repositorie-index</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="323"/>
|
||||
@ -392,22 +392,22 @@
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="359"/>
|
||||
<source>This mod can not be enabled because the following mods are incompatible with it</source>
|
||||
<translation>Denna modd kan inte aktiveras eftersom följande beroenden är inkompatibla med den</translation>
|
||||
<translation>Denna modd kan inte aktiveras eftersom följande moddar är inkompatibla med den</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="360"/>
|
||||
<source>This mod cannot be disabled because it is required by the following mods</source>
|
||||
<translation>Denna modd kan inte inaktiveras eftersom den krävs för följande beroenden</translation>
|
||||
<translation>Denna modd kan inte inaktiveras eftersom den krävs för följande modd</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="361"/>
|
||||
<source>This mod cannot be uninstalled or updated because it is required by the following mods</source>
|
||||
<translation>Denna modd kan inte avinstalleras eller uppdateras eftersom den krävs för följande beroenden</translation>
|
||||
<translation>Denna modd kan inte avinstalleras eller uppdateras eftersom den krävs för följande modd</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="362"/>
|
||||
<source>This is a submod and it cannot be installed or uninstalled separately from its parent mod</source>
|
||||
<translation>Denna undermodd/submodd kan inte installeras eller uppdateras separat från huvud-modden</translation>
|
||||
<translation>Detta är en undermodd/submodd och den kan inte installeras eller avinstalleras separat från huvud-modden</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="377"/>
|
||||
@ -467,7 +467,7 @@
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="720"/>
|
||||
<source>Downloading %1. %p% (%v MB out of %m MB) finished</source>
|
||||
<translation>Ladda ner %1. %p% (%v MB av %m MB) slutfört</translation>
|
||||
<translation>Laddar ner %1. %p% (%v MB av %m MB) slutfört</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="745"/>
|
||||
@ -494,7 +494,7 @@ Fel påträffat:
|
||||
Install successfully downloaded?</source>
|
||||
<translation>
|
||||
|
||||
Installera lyckade nedladdningar?</translation>
|
||||
Installation framgångsrikt nedladdad?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="852"/>
|
||||
@ -504,7 +504,7 @@ Installera lyckade nedladdningar?</translation>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="925"/>
|
||||
<source>Installing mod %1</source>
|
||||
<translation>Installera mod %1</translation>
|
||||
<translation>Installera modd %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="994"/>
|
||||
@ -526,7 +526,7 @@ Installera lyckade nedladdningar?</translation>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="1036"/>
|
||||
<source>Screenshot %1</source>
|
||||
<translation>Skriv ut skärm %1</translation>
|
||||
<translation>Skärmbild %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodlistview_moc.cpp" line="284"/>
|
||||
@ -570,7 +570,7 @@ Installera lyckade nedladdningar?</translation>
|
||||
<message>
|
||||
<location filename="../modManager/cmodmanager.cpp" line="200"/>
|
||||
<source>Mod is not compatible, please update VCMI and checkout latest mod revisions</source>
|
||||
<translation>Modden är inte kompatibel. Vänligen uppdatera VCMI och kontrollera att du har den senaste versionen av modden</translation>
|
||||
<translation>Modden är inte kompatibel. Vänligen uppdatera VCMI och kontrollera att du har den senaste kompatibla versionen av modden</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodmanager.cpp" line="205"/>
|
||||
@ -580,7 +580,7 @@ Installera lyckade nedladdningar?</translation>
|
||||
<message>
|
||||
<location filename="../modManager/cmodmanager.cpp" line="210"/>
|
||||
<source>Required mod %1 is not enabled</source>
|
||||
<translation>Den obligatorisk modden %1 är inte aktiverad</translation>
|
||||
<translation>Den obligatoriska modden %1 är inte aktiverad</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodmanager.cpp" line="219"/>
|
||||
@ -616,7 +616,7 @@ Installera lyckade nedladdningar?</translation>
|
||||
<message>
|
||||
<location filename="../modManager/cmodmanager.cpp" line="322"/>
|
||||
<source>Failed to extract mod data</source>
|
||||
<translation>Det gick inte att extrahera data från modd</translation>
|
||||
<translation>Misslyckades att extrahera data från modd</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../modManager/cmodmanager.cpp" line="350"/>
|
||||
@ -661,7 +661,7 @@ Installera lyckade nedladdningar?</translation>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="593"/>
|
||||
<source>VSync</source>
|
||||
<translation>Vertikal synkronisering</translation>
|
||||
<translation>Vertikal-synkronisering (VSync)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="490"/>
|
||||
@ -691,7 +691,7 @@ Installera lyckade nedladdningar?</translation>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="835"/>
|
||||
<source>Software Cursor</source>
|
||||
<translation>Programvarumarkör (muspekare)</translation>
|
||||
<translation>Programvarustyrd muspekare</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="1166"/>
|
||||
@ -731,7 +731,7 @@ Installera lyckade nedladdningar?</translation>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="1158"/>
|
||||
<source>Upscaling Filter</source>
|
||||
<translation>Förstoringsfilter</translation>
|
||||
<translation>Uppskalnings-filter</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="317"/>
|
||||
@ -766,7 +766,7 @@ Installera lyckade nedladdningar?</translation>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="1144"/>
|
||||
<source>Show Tutorial again</source>
|
||||
<translation>Visa övningsgenomgången igen</translation>
|
||||
<translation>Visa handledningen/övningsgenomgången igen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="1151"/>
|
||||
@ -853,7 +853,7 @@ Exklusivt helskärmsläge - spelet kommer att täcka hela skärmen och använda
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="407"/>
|
||||
<source>Borderless fullscreen</source>
|
||||
<translation>Kantlöst fönsterläge</translation>
|
||||
<translation>Kantlös helskärm</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="412"/>
|
||||
@ -923,7 +923,7 @@ Exklusivt helskärmsläge - spelet kommer att täcka hela skärmen och använda
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="646"/>
|
||||
<source>Check on startup</source>
|
||||
<translation>Kontrollera vid start</translation>
|
||||
<translation>Kontrollera vid uppstart</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../settingsView/csettingsview_moc.ui" line="828"/>
|
||||
@ -1151,12 +1151,12 @@ Exklusivt helskärmsläge - spelet kommer att täcka hela skärmen och använda
|
||||
<location filename="../firstLaunch/firstlaunch_moc.ui" line="504"/>
|
||||
<source>If you own Heroes III on gog.com you can download backup offline installer from gog.com, and VCMI will import Heroes III data using offline installer.
|
||||
Offline installer consists of two parts, .exe and .bin. Make sure you download both of them.</source>
|
||||
<translation>Om du äger Heroes III från GOG.com kan du ladda ner backup offline-installationsprogrammet från GOG.com - VCMI kommer att importera Heroes III-data med hjälp av offline-installationsprogrammet. Offline-installationsprogrammet består av två delar, en .exe och en .bin. Se till att ladda ner båda.</translation>
|
||||
<translation>Om du äger Heroes III från GOG.com kan du ladda ner backup offline-installationsprogrammet från 'GOG.com'. VCMI kommer att importera Heroes III-data med hjälp av offline-installationsprogrammet. Offline-installationsprogrammet består av två delar, en '.exe'- och en '.bin'fil. Se till att ladda ner båda.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../firstLaunch/firstlaunch_moc.ui" line="622"/>
|
||||
<source>Install a translation of Heroes III in your preferred language</source>
|
||||
<translation>Installera en översättning av Heroes III på ditt föredragna språk</translation>
|
||||
<translation>Installera en översättning av Heroes III på det språk du föredrar</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../firstLaunch/firstlaunch_moc.ui" line="867"/>
|
||||
@ -1166,12 +1166,12 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b
|
||||
<message>
|
||||
<location filename="../firstLaunch/firstlaunch_moc.ui" line="155"/>
|
||||
<source>VCMI on Github</source>
|
||||
<translation>VCMI på Github</translation>
|
||||
<translation>VCMI på 'Github'</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../firstLaunch/firstlaunch_moc.ui" line="162"/>
|
||||
<source>VCMI on Discord</source>
|
||||
<translation>VCMI på Discord</translation>
|
||||
<translation>VCMI på 'Discord'</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../firstLaunch/firstlaunch_moc.ui" line="178"/>
|
||||
@ -1245,7 +1245,7 @@ Heroes® of Might and Magic® III HD stöds för närvarande inte!</translation>
|
||||
<message>
|
||||
<location filename="../firstLaunch/firstlaunch_moc.ui" line="689"/>
|
||||
<source>Optionally, you can install additional mods either now, or at any point later, using the VCMI Launcher</source>
|
||||
<translation>Valfritt kan du installera ytterligare moddar antingen nu eller när som helst senare med hjälp av 'VCMI Launcher'</translation>
|
||||
<translation>Du kan välja att installera ytterligare moddar, antingen nu eller vid ett senare tillfälle med hjälp av 'VCMI Launchern'</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../firstLaunch/firstlaunch_moc.ui" line="788"/>
|
||||
@ -1276,7 +1276,7 @@ Heroes® of Might and Magic® III HD stöds för närvarande inte!</translation>
|
||||
<location filename="../firstLaunch/firstlaunch_moc.cpp" line="313"/>
|
||||
<source>Select %1 file...</source>
|
||||
<comment>param is file extension</comment>
|
||||
<translation>Välj filen %1...</translation>
|
||||
<translation>Välj filen %1 ...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../firstLaunch/firstlaunch_moc.cpp" line="314"/>
|
||||
@ -1307,7 +1307,7 @@ Heroes® of Might and Magic® III HD stöds för närvarande inte!</translation>
|
||||
<message>
|
||||
<location filename="../firstLaunch/firstlaunch_moc.cpp" line="342"/>
|
||||
<source>GOG installer</source>
|
||||
<translation>GOG installationsprogram</translation>
|
||||
<translation>GOG-Installationsprogram</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../firstLaunch/firstlaunch_moc.cpp" line="339"/>
|
||||
@ -1336,7 +1336,7 @@ Heroes® of Might and Magic® III HD stöds för närvarande inte!</translation>
|
||||
<location filename="../firstLaunch/firstlaunch_moc.cpp" line="445"/>
|
||||
<source>Failed to detect valid Heroes III data in chosen directory.
|
||||
Please select directory with installed Heroes III data.</source>
|
||||
<translation>Det går inte att upptäcka giltiga Heroes III-data i den valda katalogen. Välj en mapp där Heroes III-data finns.</translation>
|
||||
<translation>Misslyckades med att upptäcka giltiga Heroes III-data i den valda mappen. Vänligen välj en mapp där Heroes III-data finns installerat.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../firstLaunch/firstlaunch_moc.cpp" line="383"/>
|
||||
@ -1346,14 +1346,14 @@ Please select directory with installed Heroes III data.</source>
|
||||
<message>
|
||||
<location filename="../firstLaunch/firstlaunch_moc.cpp" line="399"/>
|
||||
<source>Extracting error!</source>
|
||||
<translation>Extraktionsfel!</translation>
|
||||
<translation>Fel vid extrahering!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../firstLaunch/firstlaunch_moc.cpp" line="469"/>
|
||||
<source>Heroes III: HD Edition files are not supported by VCMI.
|
||||
Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death.</source>
|
||||
<translation>Heroes III HD Edition-filer stöds inte av VCMI.
|
||||
Välj en mapp som innehåller data från Heroes III: Complete Edition eller Heroes III: Shadow of Death.</translation>
|
||||
Vänligen välj en mapp som innehåller data från Heroes III: Complete Edition eller Heroes III: Shadow of Death.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../firstLaunch/firstlaunch_moc.cpp" line="474"/>
|
||||
@ -1489,7 +1489,7 @@ Orsak till fel: </translation>
|
||||
<message>
|
||||
<location filename="../mainwindow_moc.ui" line="20"/>
|
||||
<source>VCMI Launcher</source>
|
||||
<translation>VCMI Launcher</translation>
|
||||
<translation>VCMI-startprogram (VCMI Launcher)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow_moc.ui" line="53"/>
|
||||
@ -1514,7 +1514,7 @@ Orsak till fel: </translation>
|
||||
<message>
|
||||
<location filename="../mainwindow_moc.ui" line="259"/>
|
||||
<source>Start game</source>
|
||||
<translation>Starta ett spel</translation>
|
||||
<translation>Starta spelet</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
Loading…
x
Reference in New Issue
Block a user