Home | History | Annotate | Download | only in fxge
      1 // Copyright 2017 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "core/fxge/cfx_color.h"
      8 
      9 #include <algorithm>
     10 
     11 #include "core/fpdfapi/parser/cpdf_array.h"
     12 #include "core/fpdfapi/parser/cpdf_simple_parser.h"
     13 
     14 namespace {
     15 
     16 bool InRange(float comp) {
     17   return comp >= 0.0f && comp <= 1.0f;
     18 }
     19 
     20 CFX_Color ConvertCMYK2GRAY(float dC, float dM, float dY, float dK) {
     21   if (!InRange(dC) || !InRange(dM) || !InRange(dY) || !InRange(dK))
     22     return CFX_Color(CFX_Color::kGray);
     23   return CFX_Color(
     24       CFX_Color::kGray,
     25       1.0f - std::min(1.0f, 0.3f * dC + 0.59f * dM + 0.11f * dY + dK));
     26 }
     27 
     28 CFX_Color ConvertGRAY2CMYK(float dGray) {
     29   if (!InRange(dGray))
     30     return CFX_Color(CFX_Color::kCMYK);
     31   return CFX_Color(CFX_Color::kCMYK, 0.0f, 0.0f, 0.0f, 1.0f - dGray);
     32 }
     33 
     34 CFX_Color ConvertGRAY2RGB(float dGray) {
     35   if (!InRange(dGray))
     36     return CFX_Color(CFX_Color::kRGB);
     37   return CFX_Color(CFX_Color::kRGB, dGray, dGray, dGray);
     38 }
     39 
     40 CFX_Color ConvertRGB2GRAY(float dR, float dG, float dB) {
     41   if (!InRange(dR) || !InRange(dG) || !InRange(dB))
     42     return CFX_Color(CFX_Color::kGray);
     43   return CFX_Color(CFX_Color::kGray, 0.3f * dR + 0.59f * dG + 0.11f * dB);
     44 }
     45 
     46 CFX_Color ConvertCMYK2RGB(float dC, float dM, float dY, float dK) {
     47   if (!InRange(dC) || !InRange(dM) || !InRange(dY) || !InRange(dK))
     48     return CFX_Color(CFX_Color::kRGB);
     49   return CFX_Color(CFX_Color::kRGB, 1.0f - std::min(1.0f, dC + dK),
     50                    1.0f - std::min(1.0f, dM + dK),
     51                    1.0f - std::min(1.0f, dY + dK));
     52 }
     53 
     54 CFX_Color ConvertRGB2CMYK(float dR, float dG, float dB) {
     55   if (!InRange(dR) || !InRange(dG) || !InRange(dB))
     56     return CFX_Color(CFX_Color::kCMYK);
     57 
     58   float c = 1.0f - dR;
     59   float m = 1.0f - dG;
     60   float y = 1.0f - dB;
     61   return CFX_Color(CFX_Color::kCMYK, c, m, y, std::min(c, std::min(m, y)));
     62 }
     63 
     64 }  // namespace
     65 
     66 // Static.
     67 CFX_Color CFX_Color::ParseColor(const CPDF_Array& array) {
     68   CFX_Color rt;
     69   switch (array.GetCount()) {
     70     case 1:
     71       rt = CFX_Color(CFX_Color::kGray, array.GetFloatAt(0));
     72       break;
     73     case 3:
     74       rt = CFX_Color(CFX_Color::kRGB, array.GetFloatAt(0), array.GetFloatAt(1),
     75                      array.GetFloatAt(2));
     76       break;
     77     case 4:
     78       rt = CFX_Color(CFX_Color::kCMYK, array.GetFloatAt(0), array.GetFloatAt(1),
     79                      array.GetFloatAt(2), array.GetFloatAt(3));
     80       break;
     81   }
     82   return rt;
     83 }
     84 
     85 // Static.
     86 CFX_Color CFX_Color::ParseColor(const ByteString& str) {
     87   CPDF_SimpleParser syntax(str.AsStringView());
     88   if (syntax.FindTagParamFromStart("g", 1))
     89     return CFX_Color(CFX_Color::kGray, FX_atof(syntax.GetWord()));
     90 
     91   if (syntax.FindTagParamFromStart("rg", 3)) {
     92     float f1 = FX_atof(syntax.GetWord());
     93     float f2 = FX_atof(syntax.GetWord());
     94     float f3 = FX_atof(syntax.GetWord());
     95     return CFX_Color(CFX_Color::kRGB, f1, f2, f3);
     96   }
     97   if (syntax.FindTagParamFromStart("k", 4)) {
     98     float f1 = FX_atof(syntax.GetWord());
     99     float f2 = FX_atof(syntax.GetWord());
    100     float f3 = FX_atof(syntax.GetWord());
    101     float f4 = FX_atof(syntax.GetWord());
    102     return CFX_Color(CFX_Color::kCMYK, f1, f2, f3, f4);
    103   }
    104   return CFX_Color(CFX_Color::kTransparent);
    105 }
    106 
    107 CFX_Color CFX_Color::ConvertColorType(int32_t nConvertColorType) const {
    108   if (nColorType == nConvertColorType)
    109     return *this;
    110 
    111   CFX_Color ret;
    112   switch (nColorType) {
    113     case CFX_Color::kTransparent:
    114       ret = *this;
    115       ret.nColorType = CFX_Color::kTransparent;
    116       break;
    117     case CFX_Color::kGray:
    118       switch (nConvertColorType) {
    119         case CFX_Color::kRGB:
    120           ret = ConvertGRAY2RGB(fColor1);
    121           break;
    122         case CFX_Color::kCMYK:
    123           ret = ConvertGRAY2CMYK(fColor1);
    124           break;
    125       }
    126       break;
    127     case CFX_Color::kRGB:
    128       switch (nConvertColorType) {
    129         case CFX_Color::kGray:
    130           ret = ConvertRGB2GRAY(fColor1, fColor2, fColor3);
    131           break;
    132         case CFX_Color::kCMYK:
    133           ret = ConvertRGB2CMYK(fColor1, fColor2, fColor3);
    134           break;
    135       }
    136       break;
    137     case CFX_Color::kCMYK:
    138       switch (nConvertColorType) {
    139         case CFX_Color::kGray:
    140           ret = ConvertCMYK2GRAY(fColor1, fColor2, fColor3, fColor4);
    141           break;
    142         case CFX_Color::kRGB:
    143           ret = ConvertCMYK2RGB(fColor1, fColor2, fColor3, fColor4);
    144           break;
    145       }
    146       break;
    147   }
    148   return ret;
    149 }
    150 
    151 FX_COLORREF CFX_Color::ToFXColor(int32_t nTransparency) const {
    152   CFX_Color ret;
    153   switch (nColorType) {
    154     case CFX_Color::kTransparent: {
    155       ret = CFX_Color(CFX_Color::kTransparent, 0, 0, 0, 0);
    156       break;
    157     }
    158     case CFX_Color::kGray: {
    159       ret = ConvertGRAY2RGB(fColor1);
    160       ret.fColor4 = nTransparency;
    161       break;
    162     }
    163     case CFX_Color::kRGB: {
    164       ret = CFX_Color(CFX_Color::kRGB, fColor1, fColor2, fColor3);
    165       ret.fColor4 = nTransparency;
    166       break;
    167     }
    168     case CFX_Color::kCMYK: {
    169       ret = ConvertCMYK2RGB(fColor1, fColor2, fColor3, fColor4);
    170       ret.fColor4 = nTransparency;
    171       break;
    172     }
    173   }
    174   return ArgbEncode(ret.fColor4, static_cast<int32_t>(ret.fColor1 * 255),
    175                     static_cast<int32_t>(ret.fColor2 * 255),
    176                     static_cast<int32_t>(ret.fColor3 * 255));
    177 }
    178 
    179 CFX_Color CFX_Color::operator-(float fColorSub) const {
    180   CFX_Color sRet(nColorType);
    181   switch (nColorType) {
    182     case CFX_Color::kTransparent:
    183       sRet.nColorType = CFX_Color::kRGB;
    184       sRet.fColor1 = std::max(1.0f - fColorSub, 0.0f);
    185       sRet.fColor2 = std::max(1.0f - fColorSub, 0.0f);
    186       sRet.fColor3 = std::max(1.0f - fColorSub, 0.0f);
    187       break;
    188     case CFX_Color::kRGB:
    189     case CFX_Color::kGray:
    190     case CFX_Color::kCMYK:
    191       sRet.fColor1 = std::max(fColor1 - fColorSub, 0.0f);
    192       sRet.fColor2 = std::max(fColor2 - fColorSub, 0.0f);
    193       sRet.fColor3 = std::max(fColor3 - fColorSub, 0.0f);
    194       sRet.fColor4 = std::max(fColor4 - fColorSub, 0.0f);
    195       break;
    196   }
    197   return sRet;
    198 }
    199 
    200 CFX_Color CFX_Color::operator/(float fColorDivide) const {
    201   CFX_Color sRet(nColorType);
    202   switch (nColorType) {
    203     case CFX_Color::kTransparent:
    204       sRet.nColorType = CFX_Color::kRGB;
    205       sRet.fColor1 = 1.0f / fColorDivide;
    206       sRet.fColor2 = 1.0f / fColorDivide;
    207       sRet.fColor3 = 1.0f / fColorDivide;
    208       break;
    209     case CFX_Color::kRGB:
    210     case CFX_Color::kGray:
    211     case CFX_Color::kCMYK:
    212       sRet = *this;
    213       sRet.fColor1 /= fColorDivide;
    214       sRet.fColor2 /= fColorDivide;
    215       sRet.fColor3 /= fColorDivide;
    216       sRet.fColor4 /= fColorDivide;
    217       break;
    218   }
    219   return sRet;
    220 }
    221