It is currently November 26th, 2022, 7:59 pm

Fonts

Report bugs with the Rainmeter application and suggest features.
User avatar
jsmorley
Developer
Posts: 22551
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Fonts

Post by jsmorley »

MattKing wrote: I was just being lazy, I can just use FontFace and not LocalFont. :P
LOL.. cool beans. I can stop coming up with more than likely stupid and impossible ways to get around this now.. ;-)
MattKing
Developer
Posts: 98
Joined: August 6th, 2009, 3:03 pm

Re: Fonts

Post by MattKing »

So it was actually way way way easier to not even bother with localfont thing in the Meter section, and I fixed the pathing sorta, its mostly done.

I'll post again tomorrow night, its pretty much finished.
User avatar
jsmorley
Developer
Posts: 22551
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Fonts

Post by jsmorley »

MattKing wrote:So it was actually way way way easier to not even bother with localfont thing in the Meter section, and I fixed the pathing sorta, its mostly done.

I'll post again tomorrow night, its pretty much finished.
Outstanding! Have a good rest of the evening...

One thing we could look at maybe is rather than using LocalFont1 LocalFont2 you might find it easier to have them put LocalFont=veranda.ttf|arial.ttf|Tahoma.ttf and use a "string splitter" routine to put the separate filenames into a vector (array) and then just put the array into a for / next loop to pop them off and load them. There may already be a class/function lurking in Rainmeter to do this, I know gschoppe used a similar approach for Drives=C:|D:|E: in the recyclebin plugin.

Something like this, but probably simpler as this is meant to be pretty "generic"

Code: Select all

#include <string>
#include <vector>

//! Maintains a collection of substrings that are
//! delimited by a <strong class="highlight">string</strong> of one or more characters
class Splitter {
  //! Contains the <strong class="highlight">split</strong> tokens
  std::vector<std::string> _tokens;
public:
  //! Subscript type for use with operator[]
  typedef std::vector<std::string>::size_type size_type;
public:
  //! Create and initialize a new Splitter
  //!
  //! \param[in] src The <strong class="highlight">string</strong> to <strong class="highlight">split</strong>
  //! \param[in] delim The <strong class="highlight">delimiter</strong> to <strong class="highlight">split</strong> the <strong class="highlight">string</strong> around
  Splitter ( const std::string& src, const std::string& delim )
  {
    reset ( src, delim );
  }

  //! Retrieve a <strong class="highlight">split</strong> token at the specified index
  //!
  //! \param[in] i The index to search for a token
  //! \return The token at the specified index
  //! \throw std::out_of_range If the index is invalid
  std::string& operator[] ( size_type i )
  {
    return _tokens.at ( i );
  }

  //! Retrieve the number of <strong class="highlight">split</strong> tokens
  //!
  //! \return The number of <strong class="highlight">split</strong> tokesn
  size_type size() const
  {
    return _tokens.size();
  }

  //! Re-initialize with a new soruce and <strong class="highlight">delimiter</strong>
  //!
  //! \param[in] src The <strong class="highlight">string</strong> to <strong class="highlight">split</strong>
  //! \param[in] delim The <strong class="highlight">delimiter</strong> to <strong class="highlight">split</strong> the <strong class="highlight">string</strong> around
  void reset ( const std::string& src, const std::string& delim )
  {
    std::vector<std::string> tokens;
    std::string::size_type start = 0;
    std::string::size_type end;

    for ( ; ; ) {
      end = src.find ( delim, start );
      tokens.push_back ( src.substr ( start, end - start ) );

      // We just copied the last token
      if ( end == std::string::npos )
        break;

      // Exclude the <strong class="highlight">delimiter</strong> in the next search
      start = end + delim.size();
    }

    _tokens.swap ( tokens );
  }
};

#include <iostream>

int main()
{
  const std::string line =
    "0x0002,A5651QPR87GBZ094RTF52,D,A,000001,ABC ,10000.00 , EOT";

  Splitter <strong class="highlight">split</strong> ( line, "," );

  for ( Splitter::size_type i = 0; i < <strong class="highlight">split</strong>.size(); i++ )
    std::cout<<'|'<< <strong class="highlight">split</strong>[i] <<"|\n";
}
MattKing
Developer
Posts: 98
Joined: August 6th, 2009, 3:03 pm

Re: Fonts

Post by MattKing »

jsmorley wrote: Outstanding! Have a good rest of the evening...

One thing we could look at maybe is rather than using LocalFont1 LocalFont2 you might find it easier to have them put LocalFont=veranda.ttf|arial.ttf|Tahoma.ttf and use a "string splitter" routine to put the separate filenames into a vector (array) and then just put the array into a for / next loop to pop them off and load them. There may already be a class/function lurking in Rainmeter to do this, I know gschoppe used a similar approach for Drives=C:|D:|E: in the recyclebin plugin.

Something like this, but probably simpler as this is meant to be pretty "generic"

Code: Select all

#include <string>
#include <vector>

//! Maintains a collection of substrings that are
//! delimited by a <strong class="highlight">string</strong> of one or more characters
class Splitter {
  //! Contains the <strong class="highlight">split</strong> tokens
  std::vector<std::string> _tokens;
public:
  //! Subscript type for use with operator[]
  typedef std::vector<std::string>::size_type size_type;
public:
  //! Create and initialize a new Splitter
  //!
  //! \param[in] src The <strong class="highlight">string</strong> to <strong class="highlight">split</strong>
  //! \param[in] delim The <strong class="highlight">delimiter</strong> to <strong class="highlight">split</strong> the <strong class="highlight">string</strong> around
  Splitter ( const std::string& src, const std::string& delim )
  {
    reset ( src, delim );
  }

  //! Retrieve a <strong class="highlight">split</strong> token at the specified index
  //!
  //! \param[in] i The index to search for a token
  //! \return The token at the specified index
  //! \throw std::out_of_range If the index is invalid
  std::string& operator[] ( size_type i )
  {
    return _tokens.at ( i );
  }

  //! Retrieve the number of <strong class="highlight">split</strong> tokens
  //!
  //! \return The number of <strong class="highlight">split</strong> tokesn
  size_type size() const
  {
    return _tokens.size();
  }

  //! Re-initialize with a new soruce and <strong class="highlight">delimiter</strong>
  //!
  //! \param[in] src The <strong class="highlight">string</strong> to <strong class="highlight">split</strong>
  //! \param[in] delim The <strong class="highlight">delimiter</strong> to <strong class="highlight">split</strong> the <strong class="highlight">string</strong> around
  void reset ( const std::string& src, const std::string& delim )
  {
    std::vector<std::string> tokens;
    std::string::size_type start = 0;
    std::string::size_type end;

    for ( ; ; ) {
      end = src.find ( delim, start );
      tokens.push_back ( src.substr ( start, end - start ) );

      // We just copied the last token
      if ( end == std::string::npos )
        break;

      // Exclude the <strong class="highlight">delimiter</strong> in the next search
      start = end + delim.size();
    }

    _tokens.swap ( tokens );
  }
};

#include <iostream>

int main()
{
  const std::string line =
    "0x0002,A5651QPR87GBZ094RTF52,D,A,000001,ABC ,10000.00 , EOT";

  Splitter <strong class="highlight">split</strong> ( line, "," );

  for ( Splitter::size_type i = 0; i < <strong class="highlight">split</strong>.size(); i++ )
    std::cout<<'|'<< <strong class="highlight">split</strong>[i] <<"|\n";
}

It would be possible to do that, I've already got the other way setup though(LocalFont, LocalFont2). I can change it to using the "|" as delimiters if you want. I think it would be easier to read if it was in separate keys though, some font names are super long.

I might be able to do it both if ways if I can determine if font names can have commas or | in them.
User avatar
jsmorley
Developer
Posts: 22551
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Fonts

Post by jsmorley »

MattKing wrote:
It would be possible to do that, I've already got the other way setup though(LocalFont, LocalFont2). I can change it to using the "|" as delimiters if you want. I think it would be easier to read if it was in separate keys though, some font names are super long.

I might be able to do it both if ways if I can determine if font names can have commas or | in them.
I'm not wedded to either way. I just thought it might be a bit easier for you since the string splitter routine automatically tells you how many elements there are, and you use the array in a for / next loop and don't have to "keep count" of how many fonts to load and can do all the loading in one tight loop. I can't imagine more than one or two fonts in a single .ini file though, so I don't think it is a big deal either way. I just like to ponder on these kinds of things up front as changing them after a bunch of people have created skins with the new feature means we are then "forced" into dealing with backwards compatibility.

If you do look at this, be aware that commas can be used in filenames, while the pipe cannot. So "|" might be the best choice and is consistent with one or two other places in Rainmeter that delimit strings.
MattKing
Developer
Posts: 98
Joined: August 6th, 2009, 3:03 pm

Re: Fonts

Post by MattKing »

jsmorley wrote: I'm not wedded to either way. I just thought it might be a bit easier for you since the string splitter routine automatically tells you how many elements there are, and you use the array in a for / next loop and don't have to "keep count" of how many fonts to load and can do all the loading in one tight loop. I can't imagine more than one or two fonts in a single .ini file though, so I don't think it is a big deal either way. I just like to ponder on these kinds of things up front as changing them after a bunch of people have created skins with the new feature means we are then "forced" into dealing with backwards compatibility.

If you do look at this, be aware that commas can be used in filenames, while the pipe cannot. So "|" might be the best choice and is consistent with one or two other places in Rainmeter that delimit strings.
Well it is super easy to use the LocalFont## thing as obviously that method has already been created! MeasureName, MeasureName2, etc. I stole that right out of the MeterString.cpp file.

Pathing works now:

Checks Rainmeter\Fonts, then the local skin file, then checks to see if its a full path file.

Should I like debuglog that it couldn't load the file and font family?
User avatar
jsmorley
Developer
Posts: 22551
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Fonts

Post by jsmorley »

MattKing wrote:
Sounds good. I do think writing the error with the filename and / or FontFace that failed would be good. The biggest challenge people have with 3rd party fonts is in knowing what the internal fontface name is. There will be instances when the font filename is "BiGC_BLD_1.ttf" or something and the name is "Big Caps Bold 1" and the user may have trouble getting it right.

I assume you are taking steps to figure out where \Rainmeter is, don't assume it is in Program Files. Rainmeter can be run "portable" and the .exe may reside in just about any folder. Rainy has a routine now that figures all that out so it can populate #PROGRAMPATH#, and you can crib from that if you need to.
MattKing
Developer
Posts: 98
Joined: August 6th, 2009, 3:03 pm

Re: Fonts

Post by MattKing »

Ok, I say its officially workin it fine like.

I'd say you're gonna need other devs to maybe look at how I'm finding the paths for things. I think it should be fine though.

I am using the MeterWindows reference to Rainmeter to check where Rainmeter is stored, and then I take that path and add "fonts" to it, I'm iffy on this, because I guess you could change where the fonts folder is. It maybe would be nice if Rainmeter.cpp had a method to get the fonts folder - but considering it doesn't exist yet really.. hah. I'll make a note in the code to do something about that path. (to fix it is really just changing one function call)

To get the local path of the skin I used m_SkinPath of the MeterWindow, this definitely works for sure.

If a file isn't found I DebugLog it:
"Error: Couldn't load font file: filename"

Same with if the font family can't be found.

I use Rainmeters default way of dealing with fonts that aren't found (defaults to like arial or something).

To use this new edit thingy I shall post a small example.

Code: Select all

[Rainmeter]
Author=Kaelri.LCD@gmail.com
Update=10000
LocalFont="MattKingsFont.ttf"
LocalFont2="MattKingsFont2.ttf"

[MattKingsMeter]
Meter=STRING
X=2
Y=15
FontFace="the Matt Kings Font Name"
FontFace works that same as it did before, except that it can now accept font family names that belong to any of your local fonts.



Edit:

If someone wants an explanation of what I did to implement this just ask.
User avatar
jsmorley
Developer
Posts: 22551
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Fonts

Post by jsmorley »

MattKing wrote:Ok, I say its officially workin it fine like.
Excellent! I will get this into my local version of the source this morning and start testing. Then once I do a first pass I will get it up as a branch on the code site and make a beta build using it so others can test to be sure there are no OS version related issues, issues with UAC, etc.

As to \Fonts. That is fine. While we always are mindful to support "portability", we do recommend if not enforce standardization on these sub-folder names like Skins, Addons, Plugins etc. It is my intention to eventually have #FONTSPATH# populated with C:\WhereEverRainmeter.exeIs\Fonts\ so we encourage folks to use that instead of keeping fonts in the skins folder. (to reduce duplication on the users system)
User avatar
jsmorley
Developer
Posts: 22551
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Fonts

Post by jsmorley »

Works like a champ so far!!!

[Rainmeter]
Author=Jeffrey Morley
Update=1000
LocalFont=#PROGRAMPATH#Fonts\TheSaBdCp.TTF

[Variables]
FontColor=255,255,255,255
FontFace=TheSansBold-Caps
FontSize=11
StringEffect=NONE

I removed that font from \Windows\Fonts and put it in C:\Program Files\Rainmeter\Fonts and the skin comes right up with the correct font smooth as silk.

Now going to reboot to be sure there was not some vestige of the installed font left in memory.

Edit: Yep, comes up with the right font without even a second of hesitation. Now I will load and unload the skin a few dozen times to be sure it isn't "building up" any memory usage.

Edit: Seems fine. Rainmeter ALWAYS had a small (about 150 bytes per time) memory creep when you load and unload skins or do a "refresh all" of Rainmeter. I tested it (first using your code then the original .exe/.dll) with about a dozen close skin / open skin then about a dozen refresh all while watching the memory with Process Explorer and am still getting the same 150 +- bytes creep with either the old .exe/.dll or the new ones. So it passes that test.