Esempio n. 1
0
/**
 * Clever contrast function
 *
 * It will try to adjust the foreground color such that it contrasts well with the background
 * It won't modify the hue of fg unless absolutely necessary
 * @return the adjusted form of fg
 */
QColor
ensureContrast( const QColor &bg, const QColor &fg, uint _amount = 150 )
{
    class OutputOnExit {
        public:
            OutputOnExit( const QColor &color ) : c( color ) {}
           ~OutputOnExit() { int h,s,v; c.getHsv( &h, &s, &v ); }
        private:
            const QColor &c;
    };

    // hack so I don't have to cast everywhere
    #define amount static_cast<int>(_amount)
//     #define STAMP debug() << (QValueList<int>() << fh << fs << fv);
//     #define STAMP1( string ) debug() << string << ": " << (QValueList<int>() << fh << fs << fv);
//     #define STAMP2( string, value ) debug() << string << "=" << value << ": " << (QValueList<int>() << fh << fs << fv);

    OutputOnExit allocateOnTheStack( fg );

    int bh, bs, bv;
    int fh, fs, fv;

    bg.getHsv( &bh, &bs, &bv );
    fg.getHsv( &fh, &fs, &fv );

    int dv = abs( bv - fv );

//     STAMP2( "DV", dv );

    // value is the best measure of contrast
    // if there is enough difference in value already, return fg unchanged
    if( dv > amount )
        return fg;

    int ds = abs( bs - fs );

//     STAMP2( "DS", ds );

    // saturation is good enough too. But not as good. TODO adapt this a little
    if( ds > amount )
        return fg;

    int dh = abs( bh - fh );

//     STAMP2( "DH", dh );

    if( dh > 120 ) {
        // a third of the colour wheel automatically guarentees contrast
        // but only if the values are high enough and saturations significant enough
        // to allow the colours to be visible and not be shades of grey or black

        // check the saturation for the two colours is sufficient that hue alone can
        // provide sufficient contrast
        if( ds > amount / 2 && (bs > 125 && fs > 125) )
//             STAMP1( "Sufficient saturation difference, and hues are compliemtary" );
            return fg;
        else if( dv > amount / 2 && (bv > 125 && fv > 125) )
//             STAMP1( "Sufficient value difference, and hues are compliemtary" );
            return fg;

//         STAMP1( "Hues are complimentary but we must modify the value or saturation of the contrasting colour" );

        //but either the colours are two desaturated, or too dark
        //so we need to adjust the system, although not as much
        ///_amount /= 2;
    }

    if( fs < 50 && ds < 40 ) {
       // low saturation on a low saturation is sad
       const int tmp = 50 - fs;
       fs = 50;
       if( amount > tmp )
          _amount -= tmp;
       else
          _amount = 0;
    }

    // test that there is available value to honor our contrast requirement
    if( 255 - dv < amount )
    {
        // we have to modify the value and saturation of fg
        //adjustToLimits( bv, fv, amount );

//         STAMP

        // see if we need to adjust the saturation
        if( amount > 0 )
            adjustToLimits( bs, fs, _amount );

//         STAMP

        // see if we need to adjust the hue
        if( amount > 0 )
            fh += amount; // cycles around;

//         STAMP

        return QColor::fromHsv( fh, fs, fv );
    }

//     STAMP

    if( fv > bv && bv > amount )
        return QColor::fromHsv( fh, fs, bv - amount );

//     STAMP

    if( fv < bv && fv > amount )
        return QColor::fromHsv( fh, fs, fv - amount );

//     STAMP

    if( fv > bv && (255 - fv > amount) )
        return QColor::fromHsv( fh, fs, fv + amount );

//     STAMP

    if( fv < bv && (255 - bv > amount ) )
        return QColor::fromHsv( fh, fs, bv + amount );

//     STAMP
//     debug() << "Something went wrong!\n";

    return Qt::blue;

    #undef amount
//     #undef STAMP
}
Esempio n. 2
0
/**
 * Clever contrast function
 *
 * It will try to adjust the foreground color such that it contrasts well with
 *the background
 * It won't modify the hue of fg unless absolutely necessary
 * @return the adjusted form of fg
 */
QColor ensureContrast(const QColor& bg, const QColor& fg, uint _amount = 150) {
  class OutputOnExit {
   public:
    explicit OutputOnExit(const QColor& color) : c(color) {}
    ~OutputOnExit() {
      int h, s, v;
      c.getHsv(&h, &s, &v);
    }

   private:
    const QColor& c;
  };

  OutputOnExit allocateOnTheStack(fg);

  int bh, bs, bv;
  int fh, fs, fv;

  bg.getHsv(&bh, &bs, &bv);
  fg.getHsv(&fh, &fs, &fv);

  int dv = abs(bv - fv);

  // value is the best measure of contrast
  // if there is enough difference in value already, return fg unchanged
  if (dv > static_cast<int>(_amount)) return fg;

  int ds = abs(bs - fs);

  // saturation is good enough too. But not as good. TODO adapt this a little
  if (ds > static_cast<int>(_amount)) return fg;

  int dh = abs(bh - fh);

  if (dh > 120) {
    // a third of the colour wheel automatically guarentees contrast
    // but only if the values are high enough and saturations significant enough
    // to allow the colours to be visible and not be shades of grey or black

    // check the saturation for the two colours is sufficient that hue alone can
    // provide sufficient contrast
    if (ds > static_cast<int>(_amount) / 2 && (bs > 125 && fs > 125))
      return fg;
    else if (dv > static_cast<int>(_amount) / 2 && (bv > 125 && fv > 125))
      return fg;
  }

  if (fs < 50 && ds < 40) {
    // low saturation on a low saturation is sad
    const int tmp = 50 - fs;
    fs = 50;
    if (static_cast<int>(_amount) > tmp)
      _amount -= tmp;
    else
      _amount = 0;
  }

  // test that there is available value to honor our contrast requirement
  if (255 - dv < static_cast<int>(_amount)) {
    // we have to modify the value and saturation of fg
    // adjustToLimits( bv, fv, amount );
    // see if we need to adjust the saturation
    if (static_cast<int>(_amount) > 0) adjustToLimits(bs, fs, _amount);

    // see if we need to adjust the hue
    if (static_cast<int>(_amount) > 0) fh += static_cast<int>(_amount);  // cycles around;

    return QColor::fromHsv(fh, fs, fv);
  }

  if (fv > bv && bv > static_cast<int>(_amount))
    return QColor::fromHsv(fh, fs, bv - static_cast<int>(_amount));

  if (fv < bv && fv > static_cast<int>(_amount))
    return QColor::fromHsv(fh, fs, fv - static_cast<int>(_amount));

  if (fv > bv && (255 - fv > static_cast<int>(_amount)))
    return QColor::fromHsv(fh, fs, fv + static_cast<int>(_amount));

  if (fv < bv && (255 - bv > static_cast<int>(_amount)))
    return QColor::fromHsv(fh, fs, bv + static_cast<int>(_amount));

  return Qt::blue;
}