Commit 8288143b authored by Matus Uzak's avatar Matus Uzak
Browse files

DOC: Improvements in processing of the background shading.

* Sharing one conversion function that translates the shading information
  into a color in the format "#RRGGBB".
* Returning a reasonable default instead of shading patterns at the moment.
* Also some readability improvements.

BUG:273549
parent 5afa2899
......@@ -22,8 +22,8 @@
*/
#include "conversion.h"
#include "msdoc.h"
#include "conversion.h"
#include <wv2/src/word97_generated.h>
#include <wv2/src/functordata.h>
......@@ -186,14 +186,32 @@ int Conversion::fillPatternStyle(int ipat)
}
}
uint Conversion::shadingPatternToColor(int ipat)
QString Conversion::contrastFontColor(QString name)
{
uint resultColor = 0xffffff, grayLevel = 0;
QColor color(name);
int d = 0;
// counting the perceptive luminance - human eye favors green color...
double a = 1 - (0.299 * color.red() + 0.587 * color.green() + 0.114 * color.blue()) / 255;
if (a < 0.5) {
d = 0; // bright colors - black font
} else {
d = 255; // dark colors - white font
}
return QColor(d, d, d).name();
}
quint32 Conversion::shadingPatternToColor(const quint16 ipat)
{
quint32 resultColor = 0xff000000;
uint grayLevel = 0;
bool ok;
// try to convert ipat to gray level
grayLevel = ditheringToGray(ipat, &ok);
//looking for a contrast color to the current background
if (!ok) {
return resultColor;
}
......@@ -202,7 +220,7 @@ uint Conversion::shadingPatternToColor(int ipat)
return resultColor;
}
QString Conversion::shdToColorStr(const wvWare::Word97::SHD& shd)
QString Conversion::shdToColorStr(const wvWare::Word97::SHD& shd, QString color)
{
QString ret;
if (shd.shdAutoOrNill) return ret;
......@@ -219,26 +237,31 @@ QString Conversion::shdToColorStr(const wvWare::Word97::SHD& shd)
// to 0xFF is referred to as cvAuto.
//
if (shd.cvBack == 0xff000000) {
kDebug(30513) << "Automatic color required!";
break;
ret = contrastFontColor(color);
} else {
ret.append(QString::number(shd.cvBack | 0xff000000, 16).right(6).toUpper());
ret.prepend('#');
}
ret.append(QString::number(shd.cvBack | 0xff000000, 16).right(6).toUpper());
ret.prepend('#');
break;
case ipatNil:
break;
default:
{
uint grayClr = shadingPatternToColor(shd.ipat);
ret.append(QString::number(grayClr | 0xff000000, 16).right(6).toUpper());
ret.prepend('#');
//handle remaining Ipat values
quint32 grayClr = shadingPatternToColor(shd.ipat);
if (grayClr == 0xff000000) {
ret = contrastFontColor(color);
} else {
ret.append(QString::number(grayClr | 0xff000000, 16).right(6).toUpper());
ret.prepend('#');
}
}
break;
}
return ret;
}
int Conversion::ditheringToGray(int ipat, bool* ok)
int Conversion::ditheringToGray(const quint16 ipat, bool* ok)
{
*ok = true; // optimistic ;)
switch (ipat) {
......@@ -267,10 +290,24 @@ int Conversion::ditheringToGray(int ipat, bool* ok)
case ipatPct90:
return (255 - qRound(0.9 * 255));
/*
* TODO: ipatDkHorizontal, ipatDkVertical, ipatDkForeDiag, ipatDkBackDiag,
* ipatDkCross, ipatDkDiagCross, ipatHorizontal, ipatVertical,
* ipatForeDiag, ipatBackDiag, ipatCross, ipatDiagCross
* TODO: Implementation required, returning default to at least show the
* user that some type of shading is applied.
*/
case ipatDkHorizontal:
case ipatDkVertical:
case ipatDkForeDiag:
case ipatDkBackDiag:
case ipatDkCross:
case ipatDkDiagCross:
case ipatHorizontal:
case ipatVertical:
case ipatForeDiag:
case ipatBackDiag:
case ipatCross:
case ipatDiagCross:
kDebug(30513) << "Unsupported shading pattern (0x" << hex << ipat << ")";
return (255 - qRound(0.3 * 255));
case ipatPctNew2:
return (255 - qRound(0.025 * 255));
case ipatPctNew7:
......@@ -705,4 +742,3 @@ QString Conversion::rncToStartNumberingAt(int rnc)
return "page";
}
}
......@@ -41,7 +41,7 @@ namespace wvWare
}
/**
* Static methods for simple MSWord->KWord conversions (enums etc.)
* Static methods for simple DOC->ODT conversions (enums etc.)
*/
namespace Conversion
{
......@@ -106,18 +106,26 @@ namespace Conversion
/**
* Hackery for gray levels.
*/
int ditheringToGray(int ipat, bool* ok);
int ditheringToGray(const quint16 ipat, bool* ok);
/**
* Convert shading pattern (ipat) to RGB color.
*/
uint shadingPatternToColor(int ipat);
quint32 shadingPatternToColor(const quint16 ipat);
/**
* Convert the shading information to a color string.
* @param SHD structure
* @param current background-color in the format "#RRGGBB"
* @return color in the format "#RRGGBB" or an empty string.
*/
QString shdToColorStr(const wvWare::Word97::SHD& shd);
QString shdToColorStr(const wvWare::Word97::SHD& shd, QString color);
/**
* @return the name of a color contrasting to the provided background color
* in the format "#RRGGBB".
*/
QString contrastFontColor(QString name);
/**
* Convert linespacing struct to string.
......
......@@ -129,7 +129,8 @@ public:
bool bodyFound(void) const { return m_bodyFound; }
/**
* Add element val to the backgroud-color stack.
* Add a color item to the backgroud-color stack.
* @param color in the format "#RRGGBB"
*/
void addBgColor(const QString val) { m_bgColors.push(val); }
......@@ -140,11 +141,12 @@ public:
/**
* Update the last item of the background-color stack.
* @param color in the format "#RRGGBB"
*/
void updateBgColor(const QString val) { m_bgColors.pop(); m_bgColors.push(val); }
/**
* @return the current background-color.
* @return the current background-color in the format "#RRGGBB".
*/
QString currentBgColor(void) { return m_bgColors.isEmpty() ? QString() : m_bgColors.top(); }
......
......@@ -567,7 +567,8 @@ void Paragraph::applyParagraphProperties(const wvWare::ParagraphProperties& prop
(refPap->shd.cvBack != pap.shd.cvBack) ||
(refPap->shd.shdAutoOrNill && !pap.shd.shdAutoOrNill) )
{
QString color = Conversion::shdToColorStr(pap.shd);
//TODO: current background color required
QString color = Conversion::shdToColorStr(pap.shd, "0x000000");
if (!color.isEmpty()) {
setBgColor(color);
} else {
......@@ -819,7 +820,7 @@ void Paragraph::applyCharacterProperties(const wvWare::Word97::CHP* chp, KoGenSt
QString color;
//use the color context to set the proper font color
if (chp->cv == wvWare::Word97::cvAuto) {
color = contrastFontColor(bgColor);
color = Conversion::contrastFontColor(bgColor);
} else {
color = QString('#' + QString::number(chp->cv | 0xff000000, 16).right(6).toUpper());
}
......@@ -929,10 +930,11 @@ void Paragraph::applyCharacterProperties(const wvWare::Word97::CHP* chp, KoGenSt
}
if (!refChp || refChp->shd.cvBack != chp->shd.cvBack) {
if (chp->shd.cvBack != 0xff000000)
style->addProperty(QString("fo:background-color"), '#' + QString::number(chp->shd.cvBack | 0xff000000, 16).right(6).toUpper(), KoGenStyle::TextType);
else
style->addProperty("fo:background-color", "transparent", KoGenStyle::TextType);
QString color = Conversion::shdToColorStr(chp->shd, bgColor);
if (color.isEmpty()) {
color = "transparent";
}
style->addProperty("fo:background-color", color, KoGenStyle::TextType);
}
//fShadow = text has shadow if 1
......@@ -1098,23 +1100,6 @@ QString Paragraph::createTextStyle(wvWare::SharedPtr<const wvWare::Word97::CHP>
return textStyleName;
}
QString Paragraph::contrastFontColor(QString name)
{
QColor color(name);
int d = 0;
// counting the perceptive luminance - human eye favors green color...
double a = 1 - (0.299 * color.red() + 0.587 * color.green() + 0.114 * color.blue()) / 255;
if (a < 0.5) {
d = 0; // bright colors - black font
} else {
d = 255; // dark colors - white font
}
return QColor(d, d, d).name();
}
const char* getStrokeValue(const uint brcType)
{
//TODO: create corresponding dash styles
......
......@@ -90,12 +90,6 @@ public:
*/
static void setBgColor(QString val) { m_bgColor = val; }
/**
* @return the name of a color contrasting to the background color of the
* provided name.
*/
static QString contrastFontColor(QString name);
/**
* A special purpose method, which creates a KoGenStyle for a <text:span>
* element and inserts it into the styles collection. Use this function if
......
......@@ -628,7 +628,7 @@ void KWordTableHandler::tableCellStart()
}
//process shading information
QString color = Conversion::shdToColorStr(shd);
QString color = Conversion::shdToColorStr(shd, document()->currentBgColor());
if (!color.isEmpty()) {
cellStyle.addProperty("fo:background-color", color);
//add the current background-color to stack
......@@ -723,7 +723,7 @@ void KWordTableHandler::tableCellEnd()
const wvWare::Word97::TC& tc = m_tap->rgtc[ m_column ];
const wvWare::Word97::SHD& shd = m_tap->rgshd[ m_column ];
if ( !Conversion::shdToColorStr(shd).isEmpty() &&
if ( !Conversion::shdToColorStr(shd, document()->currentBgColor()).isEmpty() &&
!(tc.fVertMerge && !tc.fVertRestart) )
{
document()->rmBgColor();
......
......@@ -52,7 +52,7 @@ Word97::BRC toWord97(const Word95::BRC &s) {
ret.brcType = 7;
}
ret.fShadow = s.fShadow;
ret.cv = Word97::icoToRGB(s.ico);
ret.cv = Word97::icoToCOLORREF(s.ico);
ret.dptSpace = s.dxpSpace;
return ret;
}
......@@ -229,7 +229,7 @@ Word97::CHP toWord97(const Word95::CHP &s) {
ret.dxaSpace=s.dxaSpace;
ret.iss=s.iss;
ret.fSysVanish=s.fSysVanish;
ret.cv= Word97::icoToRGB(s.ico);
ret.cv= Word97::icoToCOLORREF(s.ico);
ret.kul=s.kul;
ret.hpsPos=s.hpsPos;
ret.lid=s.lid;
......@@ -911,8 +911,8 @@ Word97::SHD toWord97(const Word95::SHD &s) {
Word97::SHD ret;
ret.cvFore=Word97::icoToRGB(s.icoFore);
ret.cvBack=Word97::icoToRGB(s.icoBack);
ret.cvFore=Word97::icoToCOLORREF(s.icoFore);
ret.cvBack=Word97::icoToCOLORREF(s.icoBack);
ret.ipat=s.ipat;
return ret;
......
......@@ -587,30 +587,29 @@ bool Style::validate(const U16 istd, const U16 rglpstd_cnt, const std::vector<St
//TODO: check the m_std.stk
m_invalid = true;
if ((m_std->istdBase != 0x0fff) &&
(m_std->istdBase >= rglpstd_cnt)) {
wvlog << "istdBase - invalid index into rglpstd!" << endl;
m_invalid = true;
return false;
}
if (m_std->istdBase == istd) {
wvlog << "istdBase MUST NOT be same as istd!" << endl;
m_invalid = true;
return false;
}
if ((m_std->istdBase != 0x0fff) &&
styles[m_std->istdBase]->isEmpty()) {
wvlog << "istdBase - style definition EMPTY!" << endl;
m_invalid = true;
return false;
}
if ((m_std->istdNext != 0x0fff) &&
(m_std->istdNext >= rglpstd_cnt)) {
wvlog << "istdNext - invalid index into rglpstd!" << endl;
m_invalid = true;
return false;
}
//TODO: Why did I disable this one ???
// if (m_std->istdNext == istd) {
// wvlog << "istdNext MUST NOT be same as istd!" << endl;
// return false;
......@@ -618,9 +617,10 @@ bool Style::validate(const U16 istd, const U16 rglpstd_cnt, const std::vector<St
if ((m_std->istdNext != 0x0fff) &&
styles[m_std->istdNext]->isEmpty()) {
wvlog << "istdNext - style definition EMPTY!" << endl;
m_invalid = true;
return false;
}
m_invalid = false;
return true;
}
......@@ -640,7 +640,9 @@ void Style::unwrapStyle( const StyleSheet& stylesheet, WordVersion version )
if ( m_std->istdBase != 0x0fff ) {
parentStyle = stylesheet.styleByIndex( m_std->istdBase );
if ( parentStyle ) {
#ifdef WV2_DEBUG_SPRMS
wvlog << "#### parent style ASCII Name: '" << parentStyle->name().ascii() << "'" << endl;
#endif
const_cast<Style*>( parentStyle )->unwrapStyle( stylesheet, version );
m_properties->pap() = parentStyle->paragraphProperties().pap();
*m_chp = parentStyle->chp();
......@@ -681,15 +683,21 @@ void Style::unwrapStyle( const StyleSheet& stylesheet, WordVersion version )
if ( m_std->istdBase != 0x0fff ) {
parentStyle = stylesheet.styleByIndex( m_std->istdBase );
if ( parentStyle ) {
#ifdef WV2_DEBUG_SPRMS
wvlog << "#### parent style ASCII Name: '" << parentStyle->name().ascii() << "'" << endl;
#endif
const_cast<Style*>( parentStyle )->unwrapStyle( stylesheet, version );
bool ok;
m_upechpx->istd = stylesheet.indexByID( m_std->sti, ok );
#ifdef WV2_DEBUG_SPRMS
wvlog << "our istd = " << m_upechpx->istd << " sti = " << m_std->sti << endl;
#endif
mergeUpechpx( parentStyle, version );
}
else {
#ifdef WV2_DEBUG_SPRMS
wvlog << "################# NO parent style for this character style found" << endl;
#endif
}
}
else {
......
......@@ -552,10 +552,10 @@ bool SHD::read(OLEStreamReader *stream, bool preservePos) {
shifterU16=stream->readU16();
ico=shifterU16;
cvFore=Word97::icoToRGB(ico);
cvFore=Word97::icoToCOLORREF(ico);
shifterU16>>=5;
ico=shifterU16;
cvBack=Word97::icoToRGB(ico);
cvBack=Word97::icoToCOLORREF(ico);
shifterU16>>=5;
ipat=shifterU16;
......@@ -575,10 +575,10 @@ void SHD::readPtr(const U8 *ptr) {
shifterU16=readU16(ptr);
ptr+=sizeof(U16);
icoFore=shifterU16 & 0x1F;
cvFore=Word97::icoToRGB(icoFore);
cvFore=Word97::icoToCOLORREF(icoFore);
shifterU16>>=5;
icoBack=shifterU16 & 0x1F;
cvBack=Word97::icoToRGB(icoBack);
cvBack=Word97::icoToCOLORREF(icoBack);
shifterU16>>=5;
ipat=shifterU16;
......@@ -924,7 +924,7 @@ bool BRC::read(OLEStreamReader *stream, bool preservePos) {
brcType=shifterU16;
shifterU16=stream->readU16();
ico=shifterU16 & 0xFF;
cv=Word97::icoToRGB(ico);
cv=Word97::icoToCOLORREF(ico);
shifterU16>>=8;
dptSpace=shifterU16;
shifterU16>>=5;
......@@ -951,7 +951,7 @@ void BRC::readPtr(const U8 *ptr) {
shifterU16=readU16(ptr);
ptr+=sizeof(U16);
ico=shifterU16 & 0xFF;
cv=Word97::icoToRGB(ico);
cv=Word97::icoToCOLORREF(ico);
shifterU16>>=8;
dptSpace=shifterU16;
shifterU16>>=5;
......
......@@ -50,9 +50,9 @@ namespace Word97 {
const U32 cvAuto = 0xff000000;
/**
* Helper function to convert ico color codes to 24bit rgb values
* Helper function to convert ico color codes to 24bit COLORREF
*/
U32 icoToRGB(U16 ico);
U32 icoToCOLORREF(U16 ico);
/**
* Font Family Name (FFN), this code is located in the template-Word97.h
......
......@@ -627,8 +627,12 @@ void PAP::apply( const U8* grpprl, U16 count, const Style* style, const StyleShe
SPRM::apply<PAP>( this, &PAP::applyPAPSPRM, grpprl, count, style, styleSheet, dataStream, version );
}
U32 icoToRGB(U16 ico)
U32 icoToCOLORREF(U16 ico)
{
//TODO: Do not place the fAuto byte in front! The MS-ODRAW
//OfficeArtCOLORREF is an equivalent and has the byte properly at the
//end. Oooo, it's confusing ...
switch(ico)
{
case 0: //default and we choose black as most paper is white
......@@ -1420,7 +1424,7 @@ S16 CHP::applyCHPSPRM( const U8* ptr, const Style* paragraphStyle, const StyleSh
break;
case SPRM::sprmCIco: {
U16 ico = *ptr;
cv=Word97::icoToRGB(ico);
cv=Word97::icoToCOLORREF(ico);
break;
}
case SPRM::sprmCCv: {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment