sf::Text member function getFont() doesn't work? - c++

In my program I have a function that creates an outline of another sf::Text string which is as follows:
void textDisplay::createOutline(std::vector<textDisplay> &textDisplayVector, std::vector<textDisplay> &textDisplayVector2, textDisplay &textDisplay2)
{
//create text2 npc dialogue outline
textDisplay2.text.setString(textDisplayVector.back().text.getString());
textDisplay2.text.setPosition(textDisplayVector.back().text.getPosition().x + 1, textDisplayVector.back().text.getPosition().y + 1);
textDisplay2.text.setCharacterSize(textDisplayVector.back().text.getCharacterSize());
textDisplay2.text.setColor(sf::Color::Black);
//textDisplay2.text.setFont(textDisplayVector.back().text.getFont());
textDisplayVector2.push_back(textDisplay2);
}
I want to also copy the text's font, but i get this error:
'no suitable constructor exists to convert from "const sf::Font *" to "sf::Font"'.
I looked at the sfml documentation and I believe the issue lies with getFont() using a pointer rather than a reference. I have no idea how to implement this though. How can this commented out line of code that uses setFont() and getFont() be improved so that it works? All of the other lines of code work properly.

Like you suspect, the problem is that sf::Text::getFont returns a pointer to a Font, while sf::Text::setFont expects a reference to a Font as argument. Pointer != reference, therefore you get an error.
The solution is simple: Dereference (using the * operator) the pointer returned by getFont:
textDisplay2.text.setFont(*textDisplayVector.back().text.getFont());
// ^
// |
// Notice the dereference operator here

Related

Error when assigning a unique pointer that is returned by a function to a variable

I am using a library called "Pixel Game Engine", which has a Sprite and a Decal class. The documentation uses std::unique_ptr to create them, so I want to do the same to avoid any complications that may come later on.
Here is my code:
class Asset
{
private:
typedef std::unique_ptr<olc::Sprite> uniqueSprite;
typedef std::unique_ptr<olc::Decal> uniqueDecal;
private:
uniqueSprite LoadAssetImage(std::string fileName)
{
return std::make_unique<olc::Sprite>(fileName);
}
uniqueDecal MakeDecalFromSprite(uniqueSprite sprite)
{
return std::make_unique<olc::Decal>(sprite.get());
}
public:
uniqueSprite rockSprite = LoadAssetImage("rock.png"); //No Error here
uniqueDecal rockDecal = MakeDecalFromSprite(rockSprite); //Error here
};
Error:
function "std::unique_ptr<_Ty, _Dx>::unique_ptr(const std::unique_ptr<_Ty, _Dx> &) [with _Ty=olc::Sprite, _Dx=std::default_delete<olc::Sprite>]" cannot be referenced -- it is a deleted function
At first, I thought this is happening because the unique_ptr is being copied, but loading the sprite using LoadAssetImage() and assigning it to a variable works fine, so I am a little confused as to why this error is happening.
This is how the documentation loads them:
// Load Fragment Sprite
sprFragment = std::make_unique<olc::Sprite>("./gfx/tut_fragment.png");
// Create decal of fragment
decFragment = std::make_unique<olc::Decal>(sprFragment.get());
But I wanted to try something new :)
MakeDecalFromSprite passes a uniqueSprite by value, which involves making a copy. But std::unique_ptr has a deleted copy constructor so when you try to call MakeDecalFromSprite you get a compilation error.
The solution is to pass sprite by const reference instead:
uniqueDecal MakeDecalFromSprite(const uniqueSprite& sprite)
...
Then, you are not asking the compiler to make a copy.
This call:
uniqueSprite rockSprite = LoadAssetImage("rock.png");
works because of NVRO. This avoids the need to copy the function result. If this is not possible for any reason, the compiler can generate a move (std::unique_ptr is moveable).

Skia SkCanvas cannot be constructed with SkBitmap

I have a draw(SkCanvas* canvas) function.
In main() I write:
SkBitmap myBitmap;
myBitmap.allocN32Pixels(640, 480);
SkCanvas *myCanvas(&myBitmap);
draw(myCanvas);
But Visual Studio generates this error:
"a value of type "SkBitmap *" cannot be used to initialize an entity of type "SkCanvas*"
What am I doing wrong?
My draw() function clutters the post and is completely useless for this question otherwise I've posted it.
This is the construction for SkCanvas.
/** Construct a canvas with the specified bitmap to draw into.
#param bitmap Specifies a bitmap for the canvas to draw into. Its
structure are copied to the canvas.
*/
explicit SkCanvas(const SkBitmap& bitmap);
SkCanvas *myCanvas(&myBitmap);
this is a pointer to a canvas. The pointer types of SkCanvas* and SkBitmap* are unrelated.
SkCanvas myCanvas(&myBitmap);
this is a value of type myCanvas, initialized with a pointer to bitmap. If SkCanvas has a ctor taking a SkBitmap*, this should work.
It does not. It does have:
explicit SkCanvas(const SkBitmap& bitmap);
so this means:
SkCanvas myCanvas(myBitmap);
You'll probably also need to change the draw call to this:
draw(&myCanvas);
assuming that works. As a guess, you also need a refresher on the difference between pointers and values.

Parameter conversion not allowed - MQL5 - CArrayObj

I have the following object declared in my global scope:
CArrayObj *UpwardMovements = new CArrayObj;
And I want to add CUpwards objects to UpwardMovements. CUpwards inherits from CObject so it is possible to add it to the array. However, I cannot add it to the array in a method.
For instance:
void OnTick()
{
CUpwards *UpMovm = new CUpwards(ColorForUpwards);
UpwardMovements.Clear();
CalcUpwardMovement(UpMovm);
}
void CalcUpwardMovement(CUpwards &pUpMovm)
{
UpwardMovements.Add(pUpMovm);
}
I get:
'pUpMovm' - parameter conversion not allowed
If I do the same in my OnTick() method, it works.
Any help would be greatly appreciated.
Using * vs reference. Last line of OnTick(), change to
CalcUpwardMovement(*UpMovm);
Because that method uses reference.
Edit - 4/8
Weird ... does your compiler want another parenthesis? I'm just guessing. I think it should not need another parenthesis.
Your code, with my proposed fix (see "change here" comment)
void OnTick()
{
CUpwards *UpMovm = new CUpwards(ColorForUpwards);
UpwardMovements.Clear();
CalcUpwardMovement( (*UpMovm) ); // change here <<<<<<<<<<<<
}
void CalcUpwardMovement(CUpwards& pUpMovm)
{
UpwardMovements.Add(pUpMovm);
}
Perhaps you did not mean to use the reference (I see you named the formal parameter 'pUpMovm', but a reference is not a pointer. Did you change your mind one place but not the other?
Perhaps you want UpwardMovements.Add(pUpMovm) to be able to modify the local variable pointer UpMovm in OnTick() ... but in this code that would be pointless as the modified pointer would not be used.
I solved the problem as follows:
UpwardMovements.Add(GetPointer(pUpMovm));
You may want to check the pointer before this operation with CheckPointer(GetPointer(pUpMovm));

Can't use QString in a QLineEdit nor QComboBox as a parameter

I'm trying to make a function that replace the text inside a QLineEdit when the user want to revert is name to default using a QPushButton.
This is where the code is getting "saved".
`//Must get information in the DB
lineditPlayerName = new QLineEdit("Nouveau Profil");
nameAsDefault = new QString(lineditPlayerName->text());
languageAsDefault = new QString(comboBoxlanguage->currentText());`
This is the function i use to change the value back to default
//This code works
void ProfileManager::revertName(){
lineditPlayerName->setText("nameAsDefault");
btnRevertName->setEnabled(false);
}
But I need it like this :
//This code does'nt
void ProfileManager::revertName(){
lineditPlayerName->setText(NameAsDefault);
btnRevertName->setEnabled(false);
}
I can't get it to work it give's me this error:
no matching function for call to 'QLineEdit::setText(QString*&)'
Thanks
You must dereference the NameAsDefault variable
void ProfileManager::revertName(){
lineditPlayerName->setText(*NameAsDefault);
// ^ Here I dereferenced the pointer
btnRevertName->setEnabled(false);
}
The type of nameAsDefault is pointer to a QString. However QLineEdit::setText expects a QString object, not a pointer. Therefore the compiler tells you that there is no function which expects a pointer.
I did not see your declaration of the nameAsDefault variable, but since
nameAsDefault = new QString(lineditPlayerName->text());
compiles and new returns a pointer, I suppose it is a pointer.
Also, what is probably more important is that you should almost never allocate objects using new. Especially not objects from the Qt library, which are implicitly shared.

Why does the original CString get overwritten when passing a copy to the DrawText function with the DT_MODIFYSTRING option?

I've already found a workaround to this problem, but was just wondering if anyone knew what was actually happening to cause the problem I was seeing. My guess is that it has something to do with mutability of strings, but I thought the CString object accounted for that in the copy constructor.
The following code causes mFileName to be overwritten:
class File {
public:
...
CString GetFilename() {return mFileName;}
private:
CString mFileName;
};
class FileContainer {
private: File* mFile;
public:
FileContainer() {
mFile = new File("C:\temp.txt");
}
GetFilename(CString& fileName) {
fileName = mFile->GetFileName();
}
}
void UpdateText() {
FileContainer fileCnt;
CString filePath(L"");
this->fileCnt.GetFilename(filePath);
...
::DrawText(hDC, filePath, -1, &destRect, DT_PATH_ELLIPSIS | DT_MODIFYSTRING | DT_CALCRECT);
}
What happens is that the first time UpdateText is called, GetFilename returns C:\temp.txt. Assuming that the bounding rect caused the text to be truncated to "...\temp.txt" on the first call, "...\temp.txt" is what is returned from GetFilename on the second call to UpdateText.
Even more perplexing is that this didn't cause mFileName to be changed:
void UpdateText() {
FileContainer fileCnt;
CString filePath(L"");
this->fileCnt->GetFilename(filePath);
filePath = L"TEST";
}
GetFilename always returned C:\temp.txt. So it would seem that the DrawText function is somehow finding the original CString and modifying it. But how?
UPDATE: I figured I'd throw another odd chunk of code that also causes mFileName to be overwritten:
class File {
public:
...
CString GetFilename() {return CString(mFileName);}
private:
CString mFileName;
};
That seems like it should create a new object and return that new object. Yet, somehow, DrawText still overwrites mFileName.
If I change the code to the following, I don't have any issues:
class File {
public:
...
CString GetFilename() {return CString(mFileName.GetBuffer());}
private:
CString mFileName;
};
The only thing that seems to solve the problem is to construct a new CString the way I showed in the workaround. What is DrawText doing when I pass the DT_MODIFYSTRING option?
First, note that CString can be used as a raw string pointer in two ways:
operator LPCSTR - gives a pointer which should never be modified.
GetBuffer - gives a pointer to memory specifically for the purpose of modifying the string.
Now, DrawText is declared to accept a LPCSTR. So when you pass a CString object directly as in your code, it implicitly uses operator LPCSTR to give the function what it says it wants, a constant string pointer.
However, DT_MODIFYSTRING says that DrawText can modify the string it was given. So internally, DrawText must be throwing away the constness of the pointer and modifying the string anyway.
This combination is a bad thing. But the fault is mainly in the implmentation of DrawText which is violating its own declaration.
As for why this modifies other CString objects: Apparently when a CString object is copied, it delays copying the internal string memory until something tries to modify the string through a CString member function. But until that happens, the operator LPCSTR of each CString object would still point to the same shared internal memory. This is normally fine, as long as any code using it is obeying the rules of const-correctness. However, as we've already seen, DrawText with DT_MODIFYSTRING is not playing by the rules. Thus, it is overwriting memory shared by multiple CString objects.
So to fix this problem, you either need to stop using DT_MODIFYSTRING if you don't actually need the modified text. Or else you need to pass the string to DrawText using filePath.GetBuffer() and then call filePath.ReleaseBuffer() afterwards.
Well there are some discrepancies in the code that you posted:
In 'class File':
GetFileName() {return mFileName;}
There is no return type here? Also in the FileContainer class you define the stored 'File' object as a pointer, but in the GetFileName function you access it as if it was not a pointer?
File* mFile;
...
mFile.GetFileName();
As far as why this is happening well right now I can't really tell. Another work around however would be to change the GetFileName function to return a const ref, this should ensure that the returned value can never be changed.
const CString& GetFileName() { return mFileName; }