/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
*
* (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "LEScripts.h"
#include "LELanguages.h"
#include "LESwaps.h"
#include "LayoutEngine.h"
#include "ArabicLayoutEngine.h"
#include "CanonShaping.h"
#include "HanLayoutEngine.h"
#include "HangulLayoutEngine.h"
#include "IndicLayoutEngine.h"
#include "KhmerLayoutEngine.h"
#include "ThaiLayoutEngine.h"
#include "TibetanLayoutEngine.h"
#include "GXLayoutEngine.h"
#include "GXLayoutEngine2.h"
#include "ScriptAndLanguageTags.h"
#include "CharSubstitutionFilter.h"
#include "LEGlyphStorage.h"
#include "OpenTypeUtilities.h"
#include "GlyphSubstitutionTables.h"
#include "GlyphDefinitionTables.h"
#include "MorphTables.h"
#include "DefaultCharMapper.h"
#include "KernTable.h"
/* Leave this copyright notice here! It needs to go somewhere in this library. */
/* TODO: remove these? */
0x0009, 0x000A, 0x000D,
/*0x200C, 0x200D,*/ 0x200E, 0x200F,
0x2028, 0x2029, 0x202A, 0x202B, 0x202C, 0x202D, 0x202E,
0x206A, 0x206B, 0x206C, 0x206D, 0x206E, 0x206F
};
0x0009, 0x000A, 0x000D,
0x200C, 0x200D, 0x200E, 0x200F,
0x2028, 0x2029, 0x202A, 0x202B, 0x202C, 0x202D, 0x202E,
0x206A, 0x206B, 0x206C, 0x206D, 0x206E, 0x206F
};
{
if (fZWJ) {
if (ch < 0x20) {
return 0xffff;
}
return 0xffff;
}
}
return ch; // note ZWJ bypasses fFilterControls and fMirror
}
if (fFilterControls) {
le_int32 index = OpenTypeUtilities::search((le_uint32)ch, (le_uint32 *)controlChars, controlCharsCount);
return 0xFFFF;
}
}
if (fMirror) {
le_int32 index = OpenTypeUtilities::search((le_uint32) ch, (le_uint32 *)DefaultCharMapper::mirroredChars, DefaultCharMapper::mirroredCharsCount);
}
}
return ch;
}
// This is here to get it out of LEGlyphFilter.h.
// No particular reason to put it here, other than
// this is a good central location...
{
// nothing to do
}
{
// nothing to do
}
{
// nothing to do
}
{
private:
public:
virtual ~CanonMarkFilter();
};
CanonMarkFilter::CanonMarkFilter(const LEReferenceTo<GlyphDefinitionTableHeader> &gdefTable, LEErrorCode &success)
{
}
{
// nothing to do?
}
{
if(LE_FAILURE(success)) return false;
return glyphClass != 0;
}
{
};
: fGlyphStorage(NULL), fFontInstance(fontInstance), fScriptCode(scriptCode), fLanguageCode(languageCode),
{
if (LE_FAILURE(success)) {
return;
}
fGlyphStorage = new LEGlyphStorage();
if (fGlyphStorage == NULL) {
}
}
{
return fGlyphStorage->getGlyphCount();
}
void LayoutEngine::getCharIndices(le_int32 charIndices[], le_int32 indexBase, LEErrorCode &success) const
{
}
{
}
// Copy the glyphs into caller's (32-bit) glyph array, OR in extraBits
{
}
{
}
{
}
void LayoutEngine::getGlyphPosition(le_int32 glyphIndex, float &x, float &y, LEErrorCode &success) const
{
}
le_int32 LayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
{
if (LE_FAILURE(success)) {
return 0;
}
return 0;
}
return count;
}
LEReferenceTo<GlyphSubstitutionTableHeader> canonGSUBTable((GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable);
if (substitutionFilter == NULL) {
return 0;
}
if (LE_FAILURE(success)) {
delete substitutionFilter;
return 0;
}
// This is the cheapest way to get mark reordering only for Hebrew.
// We could just do the mark reordering for all scripts, but most
// of them probably don't need it...
if (fScriptCode == hebrScriptCode) {
delete substitutionFilter;
return 0;
}
}
if (LE_FAILURE(success)) {
delete substitutionFilter;
return 0;
}
if (rightToLeft) {
dir = -1;
}
}
}
outCharCount = canonGSUBTable->process(canonGSUBTable, fakeGlyphStorage, rightToLeft, scriptTag, langSysTag, (const GlyphDefinitionTableHeader*)NULL, substitutionFilter, canonFeatureMap, canonFeatureMapCount, FALSE, success);
if (LE_FAILURE(success)) {
delete substitutionFilter;
return 0;
}
/*
* The char indices array in fakeGlyphStorage has the correct mapping
* back to the original input characters. Save it in glyphStorage. The
* subsequent call to glyphStoratge.allocateGlyphArray will keep this
* array rather than allocating and initializing a new one.
*/
delete substitutionFilter;
return 0;
}
}
delete substitutionFilter;
}
return outCharCount;
}
le_int32 LayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
{
if (LE_FAILURE(success)) {
return 0;
}
return 0;
}
le_int32 outCharCount = characterProcessing(chars, offset, count, max, rightToLeft, outChars, glyphStorage, success);
LE_DELETE_ARRAY(outChars); // FIXME: a subclass may have allocated this, in which case this delete might not work...
} else {
}
return glyphStorage.getGlyphCount();
}
// Input: glyphs
// Output: positions
void LayoutEngine::positionGlyphs(LEGlyphStorage &glyphStorage, float x, float y, LEErrorCode &success)
{
if (LE_FAILURE(success)) {
return;
}
if (LE_FAILURE(success)) {
return;
}
for (i = 0; i < glyphCount; i += 1) {
}
}
void LayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse,
{
if (LE_FAILURE(success)) {
return;
}
return;
}
LEReferenceTo<GlyphDefinitionTableHeader> gdefTable((GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable,
}
// default is no adjustments
return;
}
void LayoutEngine::adjustMarkGlyphs(LEGlyphStorage &glyphStorage, LEGlyphFilter *markFilter, LEErrorCode &success)
{
float xAdjust = 0;
if (LE_FAILURE(success)) {
return;
}
if (markFilter == NULL) {
return;
}
for (p = 0; p < glyphCount; p += 1) {
}
}
}
void LayoutEngine::adjustMarkGlyphs(const LEUnicode chars[], le_int32 charCount, le_bool reverse, LEGlyphStorage &glyphStorage, LEGlyphFilter *markFilter, LEErrorCode &success)
{
float xAdjust = 0;
if (LE_FAILURE(success)) {
return;
}
if (markFilter == NULL) {
return;
}
if (reverse) {
c = glyphCount - 1;
direction = -1;
}
}
}
}
{
}
void LayoutEngine::mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, le_bool mirror,
{
if (LE_FAILURE(success)) {
return;
}
fFontInstance->mapCharsToGlyphs(chars, offset, count, reverse, &charMapper, fFilterZeroWidth, glyphStorage);
}
// Input: characters, font?
// Output: glyphs, positions, char indices
// Returns: number of glyphs
le_int32 LayoutEngine::layoutChars(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
float x, float y, LEErrorCode &success)
{
if (LE_FAILURE(success)) {
return 0;
}
return 0;
}
if (fGlyphStorage->getGlyphCount() > 0) {
fGlyphStorage->reset();
}
return glyphCount;
}
{
if(fGlyphStorage!=NULL) {
fGlyphStorage->reset();
}
}
LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, LEErrorCode &success)
{
//kerning and ligatures - by default
return LayoutEngine::layoutEngineFactory(fontInstance, scriptCode, languageCode, LE_DEFAULT_FEATURE_FLAG, success);
}
LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, LEErrorCode &success)
{
if (LE_FAILURE(success)) {
return NULL;
}
// Right now, only invoke V2 processing for Devanagari. TODO: Allow more V2 scripts as they are
// properly tested.
if ( v2ScriptTag == dev2ScriptTag && gsubTable.isValid() && gsubTable->coversScript(gsubTable, v2ScriptTag, success )) {
result = new IndicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, TRUE, gsubTable, success);
}
else if (gsubTable.isValid() && gsubTable->coversScript(gsubTable, scriptTag = OpenTypeLayoutEngine::getScriptTag(scriptCode), success)) {
switch (scriptCode) {
case bengScriptCode:
case devaScriptCode:
case gujrScriptCode:
case kndaScriptCode:
case mlymScriptCode:
case oryaScriptCode:
case guruScriptCode:
case tamlScriptCode:
case teluScriptCode:
case sinhScriptCode:
result = new IndicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, FALSE, gsubTable, success);
break;
case arabScriptCode:
result = new ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success);
break;
case hebrScriptCode:
// Disable hebrew ligatures since they have only archaic uses, see ticket #8318
result = new OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags & ~kTypoFlagLiga, gsubTable, success);
break;
case hangScriptCode:
result = new HangulOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success);
break;
case haniScriptCode:
switch (languageCode) {
case korLanguageCode:
case janLanguageCode:
case zhtLanguageCode:
case zhsLanguageCode:
result = new HanOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success);
break;
}
// note: falling through to default case.
default:
result = new OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success);
break;
}
break;
case tibtScriptCode:
result = new TibetanOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success);
break;
case khmrScriptCode:
result = new KhmerOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success);
break;
default:
result = new OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success);
break;
}
} else {
result = new GXLayoutEngine2(fontInstance, scriptCode, languageCode, morxTable, typoFlags, success);
} else {
} else {
switch (scriptCode) {
case bengScriptCode:
case devaScriptCode:
case gujrScriptCode:
case kndaScriptCode:
case mlymScriptCode:
case oryaScriptCode:
case guruScriptCode:
case tamlScriptCode:
case teluScriptCode:
case sinhScriptCode:
{
break;
}
case arabScriptCode:
//case hebrScriptCode:
result = new UnicodeArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
break;
//case hebrScriptCode:
// return new HebrewOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags);
case thaiScriptCode:
break;
case hangScriptCode:
result = new HangulOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
break;
default:
break;
}
}
}
}
delete result;
}
}
return result;
}
LayoutEngine::~LayoutEngine() {
delete fGlyphStorage;
}