This source file includes following definitions.
- processArabicFormDetection
- charactersWithArabicForm
- isCompatibleArabicForm
- isCompatibleGlyph
#include "config.h"
#if ENABLE(SVG_FONTS)
#include "platform/fonts/SVGGlyph.h"
#include "wtf/unicode/Unicode.h"
using namespace WTF::Unicode;
namespace WebCore {
enum ArabicCharShapingMode {
SNone = 0,
SRight = 1,
SDual = 2
};
static const ArabicCharShapingMode s_arabicCharShapingMode[222] = {
SRight, SRight, SRight, SRight, SDual , SRight, SDual , SRight, SDual , SDual , SDual , SDual , SDual , SRight,
SRight, SRight, SRight, SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SNone , SNone , SNone , SNone , SNone ,
SNone , SDual , SDual , SDual , SDual , SDual , SDual , SRight, SDual , SDual , SNone , SNone , SNone , SNone , SNone , SNone ,
SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone ,
SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone ,
SNone , SRight, SRight, SRight, SNone , SRight, SRight, SRight, SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual ,
SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SRight, SRight, SRight, SRight, SRight, SRight, SRight, SRight,
SRight, SRight, SRight, SRight, SRight, SRight, SRight, SRight, SRight, SRight, SDual , SDual , SDual , SDual , SDual , SDual ,
SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual ,
SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual ,
SRight, SDual , SRight, SRight, SRight, SRight, SRight, SRight, SRight, SRight, SRight, SRight, SDual , SRight, SDual , SRight,
SDual , SDual , SRight, SRight, SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone ,
SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone ,
SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SDual , SDual , SDual , SNone , SNone , SNone
};
static inline SVGGlyph::ArabicForm processArabicFormDetection(const UChar& curChar, bool& lastCharShapesRight, SVGGlyph::ArabicForm* prevForm)
{
SVGGlyph::ArabicForm curForm;
ArabicCharShapingMode shapingMode = SNone;
if (curChar >= 0x0622 && curChar <= 0x06FF)
shapingMode = s_arabicCharShapingMode[curChar - 0x0622];
if (lastCharShapesRight && shapingMode == SDual) {
if (prevForm) {
int correctedForm = (int) *prevForm + 1;
ASSERT(correctedForm >= SVGGlyph::None && correctedForm <= SVGGlyph::Medial);
*prevForm = static_cast<SVGGlyph::ArabicForm>(correctedForm);
}
curForm = SVGGlyph::Initial;
} else
curForm = shapingMode == SNone ? SVGGlyph::None : SVGGlyph::Isolated;
lastCharShapesRight = shapingMode != SNone;
return curForm;
}
Vector<SVGGlyph::ArabicForm> charactersWithArabicForm(const String& input, bool rtl)
{
Vector<SVGGlyph::ArabicForm> forms;
unsigned length = input.length();
bool containsArabic = false;
for (unsigned i = 0; i < length; ++i) {
if (isArabicChar(input[i])) {
containsArabic = true;
break;
}
}
if (!containsArabic)
return forms;
bool lastCharShapesRight = false;
if (rtl) {
for (int i = length - 1; i >= 0; --i)
forms.prepend(processArabicFormDetection(input[i], lastCharShapesRight, forms.isEmpty() ? 0 : &forms.first()));
} else {
for (unsigned i = 0; i < length; ++i)
forms.append(processArabicFormDetection(input[i], lastCharShapesRight, forms.isEmpty() ? 0 : &forms.last()));
}
return forms;
}
static inline bool isCompatibleArabicForm(const SVGGlyph& identifier, const Vector<SVGGlyph::ArabicForm>& chars, unsigned startPosition, unsigned endPosition)
{
if (chars.isEmpty())
return true;
Vector<SVGGlyph::ArabicForm>::const_iterator realEnd = chars.end();
Vector<SVGGlyph::ArabicForm>::const_iterator it = chars.begin() + startPosition;
if (it >= realEnd)
return true;
Vector<SVGGlyph::ArabicForm>::const_iterator end = chars.begin() + endPosition;
if (end >= realEnd)
end = realEnd;
for (; it != end; ++it) {
if (*it != static_cast<SVGGlyph::ArabicForm>(identifier.arabicForm) && *it != SVGGlyph::None)
return false;
}
return true;
}
bool isCompatibleGlyph(const SVGGlyph& identifier, bool isVerticalText, const String& language,
const Vector<SVGGlyph::ArabicForm>& chars, unsigned startPosition, unsigned endPosition)
{
bool valid = true;
switch (identifier.orientation) {
case SVGGlyph::Vertical:
valid = isVerticalText;
break;
case SVGGlyph::Horizontal:
valid = !isVerticalText;
break;
case SVGGlyph::Both:
break;
}
if (!valid)
return false;
if (!identifier.languages.isEmpty()) {
if (language.isEmpty())
return false;
String languagePrefix;
size_t subCodeSeparator = language.find('-');
if (subCodeSeparator != kNotFound)
languagePrefix = language.left(subCodeSeparator);
Vector<String>::const_iterator it = identifier.languages.begin();
Vector<String>::const_iterator end = identifier.languages.end();
bool found = false;
for (; it != end; ++it) {
const String& cur = *it;
if (cur == language || cur == languagePrefix) {
found = true;
break;
}
}
if (!found)
return false;
}
return isCompatibleArabicForm(identifier, chars, startPosition, endPosition);
}
}
#endif