Skip to content

Commit

Permalink
Added support for RTL(right to left) languages like Arabic and Persia…
Browse files Browse the repository at this point in the history
…n in HTML output
  • Loading branch information
ahoogol committed Jun 25, 2017
1 parent e7e6210 commit 5885c89
Show file tree
Hide file tree
Showing 17 changed files with 609 additions and 186 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@

/doxygen_docs
/doxygen.tag
/build
95 changes: 73 additions & 22 deletions qtools/qstring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11614,32 +11614,83 @@ static inline bool is_neutral(unsigned short dir) {
#endif

/*!
This function returns the basic directionality of the string (QChar::DirR for
right to left and QChar::DirL for left to right). Useful to find the right
alignment.
*/
QChar::Direction QString::basicDirection()
This function returns the directionality of the string.
\returns a value of DirLTR, DirRTL, DirMixed or DirNeutral that indicates
if the entire text represented by this text is unidirectional,
and which direction, or if it is mixed-directional or all characters are neutral.
*/
QString::Direction QString::direction() const
{
#ifndef QT_NO_UNICODETABLES
// find base direction
unsigned int pos = 0;
while ((pos < length()) &&
(at(pos) != RLE) &&
(at(pos) != LRE) &&
(at(pos) != RLO) &&
(at(pos) != LRO) &&
(at(pos).direction() > 1) &&
(at(pos).direction() != QChar::DirAL)) // not R and not L
pos++;

if ((at(pos).direction() == QChar::DirR) ||
(at(pos).direction() == QChar::DirAL) ||
(at(pos) == RLE) ||
(at(pos) == RLO))
return QChar::DirR;
// find direction
unsigned char resultDir = DirNeutral;
for (unsigned int pos = 0; pos < length(); pos++)
{
if ((at(pos) != RLE) &&
(at(pos) != LRE) &&
(at(pos) != RLO) &&
(at(pos) != LRO) &&
(at(pos).direction() > 1) &&
(at(pos).direction() != QChar::DirAL)) // not R and not L
continue;

if ((at(pos).direction() == QChar::DirR) ||
(at(pos).direction() == QChar::DirAL) ||
(at(pos) == RLE) ||
(at(pos) == RLO))
resultDir |= DirRTL;
else
resultDir |= DirLTR;
if (resultDir == DirMixed)
return DirMixed;
}
return static_cast<Direction>(resultDir);
#else
return DirLTR;
#endif
}

/*!
This function returns the basic directionality of the string. Useful to find the right
alignment.
return QChar::DirL;
The base direction is derived from the first character in the string
with bidirectional character type L, R, or AL.
If the first such character has type L, DirLTR is returned.
If the first such character has type R or AL, DirRTL is returned.
If the string does not contain any character of these types, then DirNeutral is returned.
This is a lightweight function for use when only the base direction is needed and
no further bidi processing of the text is needed.
\returns DirRTL, DirLTR or DirNeutral
*/
QString::Direction QString::basicDirection() const
{
#ifndef QT_NO_UNICODETABLES
// find base direction
unsigned int pos = 0;
while ((pos < length()) &&
(at(pos) != RLE) &&
(at(pos) != LRE) &&
(at(pos) != RLO) &&
(at(pos) != LRO) &&
(at(pos).direction() > 1) &&
(at(pos).direction() != QChar::DirAL)) // not R and not L
pos++;

if (pos == length())
return DirNeutral;

if ((at(pos).direction() == QChar::DirR) ||
(at(pos).direction() == QChar::DirAL) ||
(at(pos) == RLE) ||
(at(pos) == RLO))
return DirRTL;
return DirLTR;
#else
return DirLTR;
#endif
}

#ifndef QT_NO_UNICODETABLES
Expand Down
37 changes: 35 additions & 2 deletions qtools/qstring.h
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,38 @@ class Q_EXPORT QString
QString &operator=( QChar c );
QString &operator=( char c );

enum Direction
{
/// No strongly directional text.
/*!
* As return value for direction() or baseDirection(), it means that the source string
* is missing or empty, or contains neither left-to-right nor right-to-left characters.
*/
DirNeutral = 0x0,
/// Left-to-right text.
/*!
* - As return value for direction(), it means that the source string
* contains no right-to-left characters.
* - As return value for basicDirection(), it means that the first strong character
* of the source string has a left-to-right direction.
*/
DirLTR = 0b01,
/// Right-to-left text.
/*!
* - As return value for direction(), it means that the source string
* contains no left-to-right characters.
* - As return value for basicDirection(), it means that the first strong character
* of the source string has a right-to-left direction.
*/
DirRTL = 0b10,
/// Mixed-directional text
/*!
* As return value for direction(), it means that the source string
* contains both left-to-right and right-to-left characters.
*/
DirMixed = 0b11
};

//QT_STATIC_CONST QString null;
//bool isNull() const;

Expand Down Expand Up @@ -535,8 +567,9 @@ class Q_EXPORT QString
#endif
// new functions for BiDi
void compose();
QChar::Direction basicDirection();
QString visual(int index = 0, int len = -1);
QString::Direction direction() const;
QString::Direction basicDirection() const;
QString visual(int index = 0, int len = -1);

#ifndef QT_NO_COMPAT
const char* data() const { return latin1(); }
Expand Down
13 changes: 13 additions & 0 deletions src/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,19 @@ Go to the <a href="commands.html">next</a> section or return to the
<value name='Ukrainian'/>
<value name='Vietnamese'/>
</option>
<option type='enum' id='OUTPUT_TEXT_DIRECTION' defval='None'>
<docs>
<![CDATA[
The \c OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
documentation generated by doxygen is written. Doxygen will use this
information to generate all generated output in the proper direction.
]]>
</docs>
<value name='None'/>
<value name='LTR'/>
<value name='RTL'/>
<value name='Context'/>
</option>
<option type='bool' id='BRIEF_MEMBER_DESC' defval='1'>
<docs>
<![CDATA[
Expand Down
123 changes: 122 additions & 1 deletion src/docparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7218,8 +7218,129 @@ static QCString processCopyDoc(const char *data,uint &len)
buf.addChar(0);
return buf.get();
}
//---------------------------------------------------------------------------
QString::Direction getTextDirByConfig(const QString &text)
{
auto configDir = Config_getEnum(OUTPUT_TEXT_DIRECTION);
if (configDir == "None")
return QString::DirNeutral;
if (configDir == "Context")
return text.basicDirection();
if (configDir == "LTR")
{
auto textDir = text.direction();
if (textDir == QString::DirMixed)
return QString::DirLTR;
return textDir;
}
if (configDir == "RTL")
{
auto textDir = text.direction();
if (textDir == QString::DirMixed)
return QString::DirRTL;
return textDir;
}
return QString::DirNeutral;
}

//--------------------------------------------------------------------------
QString::Direction getTextDirByConfig(const DocNode *node)
{
auto configDir = Config_getEnum(OUTPUT_TEXT_DIRECTION);
if (configDir == "None")
return QString::DirNeutral;
if (configDir == "Context")
return node->getTextBasicDir();
if (configDir == "LTR")
{
auto textDir = node->getTextDir();
if (textDir == QString::DirMixed)
return QString::DirLTR;
return textDir;
}
if (configDir == "RTL")
{
auto textDir = node->getTextDir();
if (textDir == QString::DirMixed)
return QString::DirRTL;
return textDir;
}
return QString::DirNeutral;
}

QString::Direction getTextDirByConfig(const DocPara *para, int nodeIndex)
{
auto configDir = Config_getEnum(OUTPUT_TEXT_DIRECTION);
if (configDir == "None")
return QString::DirNeutral;
if (configDir == "Context")
return para->getTextBasicDir(nodeIndex);
if (configDir == "LTR")
{
auto textDir = para->getTextDir(nodeIndex);
if (textDir == QString::DirMixed)
return QString::DirLTR;
return textDir;
}
if (configDir == "RTL")
{
auto textDir = para->getTextDir(nodeIndex);
if (textDir == QString::DirMixed)
return QString::DirRTL;
return textDir;
}
return QString::DirNeutral;
}

QCString getDirHtmlClassOfNode(QString::Direction textDir, const char *initValue)
{
QCString classFromDir;
if (textDir == QString::DirLTR)
classFromDir = "DocNodeLTR";
else if (textDir == QString::DirRTL)
classFromDir = "DocNodeRTL";
else
classFromDir = "";

if (initValue != nullptr && !classFromDir.isEmpty())
return QCString(" class=\"") + initValue + " " + classFromDir + "\"";
if (initValue != nullptr)
return QCString(" class=\"") + initValue + "\"";
if (!classFromDir.isEmpty())
return QCString(" class=\"") + classFromDir + "\"";
return "";
}

QCString getDirHtmlClassOfPage(QCString pageTitle)
{
QCString result = "";
result += " class=\"PageDoc";
auto titleDir = getTextDirByConfig(pageTitle);
if (titleDir == QString::DirLTR)
result += " PageDocLTR-title";
else if (titleDir == QString::DirRTL)
result += " PageDocRTL-title";
result += "\"";
return result;
}

QCString getHtmlDirEmbedingChar(QString::Direction textDir)
{
if (textDir == QString::DirLTR)
return "&#x202A;";
if (textDir == QString::DirRTL)
return "&#x202B;";
return "";
}

QCString getJsDirEmbedingChar(QString::Direction textDir)
{
if (textDir == QString::DirLTR)
return "\\u202A";
if (textDir == QString::DirRTL)
return "\\u202B";
return "";
}
//---------------------------------------------------------------------------

DocRoot *validatingParseDoc(const char *fileName,int startLine,
Definition *ctx,MemberDef *md,
Expand Down
Loading

0 comments on commit 5885c89

Please sign in to comment.