os/textandloc/fontservices/textshaperplugin/IcuSource/layout/ArabicLayoutEngine.cpp
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/textandloc/fontservices/textshaperplugin/IcuSource/layout/ArabicLayoutEngine.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,209 @@
1.4 +
1.5 +/*
1.6 + *
1.7 + * (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved
1.8 + *
1.9 + */
1.10 +
1.11 +#include "LETypes.h"
1.12 +#include "LEScripts.h"
1.13 +#include "LEGlyphFilter.h"
1.14 +#include "LEGlyphStorage.h"
1.15 +#include "LayoutEngine.h"
1.16 +#include "OpenTypeLayoutEngine.h"
1.17 +#include "ArabicLayoutEngine.h"
1.18 +#include "ScriptAndLanguageTags.h"
1.19 +#include "CharSubstitutionFilter.h"
1.20 +
1.21 +#include "GlyphSubstitutionTables.h"
1.22 +#include "GlyphDefinitionTables.h"
1.23 +#include "GlyphPositioningTables.h"
1.24 +
1.25 +#include "GDEFMarkFilter.h"
1.26 +
1.27 +#include "ArabicShaping.h"
1.28 +#include "CanonShaping.h"
1.29 +
1.30 +U_NAMESPACE_BEGIN
1.31 +
1.32 +le_bool CharSubstitutionFilter::accept(LEGlyphID glyph) const
1.33 +{
1.34 + return fFontInstance->canDisplay((LEUnicode) glyph);
1.35 +}
1.36 +
1.37 +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ArabicOpenTypeLayoutEngine)
1.38 +
1.39 +ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
1.40 + le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable)
1.41 + : OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable)
1.42 +{
1.43 + /**/ fFeatureOrder = ArabicShaping::getFeatureOrder();
1.44 +}
1.45 +
1.46 +ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
1.47 + le_int32 typoFlags)
1.48 + : OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags)
1.49 +{
1.50 + // fFeatureOrder = ArabicShaping::getFeatureOrder();
1.51 +}
1.52 +
1.53 +ArabicOpenTypeLayoutEngine::~ArabicOpenTypeLayoutEngine()
1.54 +{
1.55 + // nothing to do
1.56 +}
1.57 +
1.58 +// Input: characters
1.59 +// Output: characters, char indices, tags
1.60 +// Returns: output character count
1.61 +le_int32 ArabicOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
1.62 + LEUnicode *&outChars, LEGlyphStorage &glyphStorage, LEErrorCode &success)
1.63 +{
1.64 + if (LE_FAILURE(success)) {
1.65 + return 0;
1.66 + }
1.67 +
1.68 + if (chars == NULL || offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
1.69 + success = LE_ILLEGAL_ARGUMENT_ERROR;
1.70 + return 0;
1.71 + }
1.72 +
1.73 + outChars = LE_NEW_ARRAY(LEUnicode, count);
1.74 +
1.75 + if (outChars == NULL) {
1.76 + success = LE_MEMORY_ALLOCATION_ERROR;
1.77 + return 0;
1.78 + }
1.79 +
1.80 + glyphStorage.allocateGlyphArray(count, rightToLeft, success);
1.81 + glyphStorage.allocateAuxData(success);
1.82 +
1.83 + if (LE_FAILURE(success)) {
1.84 + LE_DELETE_ARRAY(outChars);
1.85 + return 0;
1.86 + }
1.87 +
1.88 + CanonShaping::reorderMarks(&chars[offset], count, rightToLeft, outChars, glyphStorage);
1.89 +
1.90 + // Note: This processes the *original* character array so we can get context
1.91 + // for the first and last characters. This is OK because only the marks
1.92 + // will have been reordered, and they don't contribute to shaping.
1.93 + ArabicShaping::shape(chars, offset, count, max, rightToLeft, glyphStorage);
1.94 +
1.95 + return count;
1.96 +}
1.97 +
1.98 +void ArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse,
1.99 + LEGlyphStorage &glyphStorage, LEErrorCode &success)
1.100 +{
1.101 + if (LE_FAILURE(success)) {
1.102 + return;
1.103 + }
1.104 +
1.105 + if (chars == NULL || offset < 0 || count < 0) {
1.106 + success = LE_ILLEGAL_ARGUMENT_ERROR;
1.107 + return;
1.108 + }
1.109 +
1.110 + if (fGPOSTable != NULL) {
1.111 + OpenTypeLayoutEngine::adjustGlyphPositions(chars, offset, count, reverse, glyphStorage, success);
1.112 + } else if (fGDEFTable != NULL) {
1.113 + GDEFMarkFilter filter(fGDEFTable);
1.114 +
1.115 + adjustMarkGlyphs(glyphStorage, &filter, success);
1.116 + } else {
1.117 + GlyphDefinitionTableHeader *gdefTable = (GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable;
1.118 + GDEFMarkFilter filter(gdefTable);
1.119 +
1.120 + adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
1.121 + }
1.122 +}
1.123 +
1.124 +UnicodeArabicOpenTypeLayoutEngine::UnicodeArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags)
1.125 + : ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags)
1.126 +{
1.127 + fGSUBTable = (const GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable;
1.128 + fGDEFTable = (const GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable;
1.129 +
1.130 + fSubstitutionFilter = new CharSubstitutionFilter(fontInstance);
1.131 +}
1.132 +
1.133 +UnicodeArabicOpenTypeLayoutEngine::~UnicodeArabicOpenTypeLayoutEngine()
1.134 +{
1.135 + delete fSubstitutionFilter;
1.136 +}
1.137 +
1.138 +// "glyphs", "indices" -> glyphs, indices
1.139 +le_int32 UnicodeArabicOpenTypeLayoutEngine::glyphPostProcessing(LEGlyphStorage &tempGlyphStorage, LEGlyphStorage &glyphStorage, LEErrorCode &success)
1.140 +{
1.141 + if (LE_FAILURE(success)) {
1.142 + return 0;
1.143 + }
1.144 +
1.145 + // FIXME: we could avoid the memory allocation and copy if we
1.146 + // made a clone of mapCharsToGlyphs which took the fake glyphs
1.147 + // directly.
1.148 + le_int32 tempGlyphCount = tempGlyphStorage.getGlyphCount();
1.149 + LEUnicode *tempChars = LE_NEW_ARRAY(LEUnicode, tempGlyphCount);
1.150 +
1.151 + if (tempChars == NULL) {
1.152 + success = LE_MEMORY_ALLOCATION_ERROR;
1.153 + return 0;
1.154 + }
1.155 +
1.156 + for (le_int32 i = 0; i < tempGlyphCount; i += 1) {
1.157 + tempChars[i] = (LEUnicode) LE_GET_GLYPH(tempGlyphStorage[i]);
1.158 + }
1.159 +
1.160 + glyphStorage.adoptCharIndicesArray(tempGlyphStorage);
1.161 +
1.162 + ArabicOpenTypeLayoutEngine::mapCharsToGlyphs(tempChars, 0, tempGlyphCount, FALSE, TRUE, glyphStorage, success);
1.163 +
1.164 + LE_DELETE_ARRAY(tempChars);
1.165 +
1.166 + return tempGlyphCount;
1.167 +}
1.168 +
1.169 +void UnicodeArabicOpenTypeLayoutEngine::mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, le_bool /*mirror*/, LEGlyphStorage &glyphStorage, LEErrorCode &success)
1.170 +{
1.171 + if (LE_FAILURE(success)) {
1.172 + return;
1.173 + }
1.174 +
1.175 + if (chars == NULL || offset < 0 || count < 0) {
1.176 + success = LE_ILLEGAL_ARGUMENT_ERROR;
1.177 + return;
1.178 + }
1.179 +
1.180 + le_int32 i, dir = 1, out = 0;
1.181 +
1.182 + if (reverse) {
1.183 + out = count - 1;
1.184 + dir = -1;
1.185 + }
1.186 +
1.187 + glyphStorage.allocateGlyphArray(count, reverse, success);
1.188 +
1.189 + for (i = 0; i < count; i += 1, out += dir) {
1.190 + glyphStorage[out] = (LEGlyphID) chars[offset + i];
1.191 + }
1.192 +}
1.193 +
1.194 +void UnicodeArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse,
1.195 + LEGlyphStorage &glyphStorage, LEErrorCode &success)
1.196 +{
1.197 + if (LE_FAILURE(success)) {
1.198 + return;
1.199 + }
1.200 +
1.201 + if (chars == NULL || offset < 0 || count < 0) {
1.202 + success = LE_ILLEGAL_ARGUMENT_ERROR;
1.203 + return;
1.204 + }
1.205 +
1.206 + GDEFMarkFilter filter(fGDEFTable);
1.207 +
1.208 + adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
1.209 +}
1.210 +
1.211 +U_NAMESPACE_END
1.212 +