ICU-5565 Merge loengine branch to trunk!

X-SVN-Rev: 21808
This commit is contained in:
Eric Mader 2007-06-22 03:57:45 +00:00
parent ac329166b4
commit b2dc4eced5
52 changed files with 5150 additions and 47 deletions

3
.gitattributes vendored
View File

@ -88,6 +88,9 @@ icu4c/source/i18n/persncal.cpp -text
icu4c/source/i18n/persncal.h -text icu4c/source/i18n/persncal.h -text
icu4c/source/i18n/reldtfmt.cpp -text icu4c/source/i18n/reldtfmt.cpp -text
icu4c/source/i18n/reldtfmt.h -text icu4c/source/i18n/reldtfmt.h -text
icu4c/source/samples/layout/cgnomelayout.c -text
icu4c/source/samples/layout/gnomeglue.cpp -text
icu4c/source/samples/layout/gnomeglue.h -text
icu4c/source/samples/ucnv/data02.bin -text icu4c/source/samples/ucnv/data02.bin -text
icu4c/source/test/compat/Makefile.in -text icu4c/source/test/compat/Makefile.in -text
icu4c/source/test/compat/readme.txt -text icu4c/source/test/compat/readme.txt -text

View File

@ -1,5 +1,5 @@
/* /*
* (C) Copyright IBM Corp. 1998 - 2005 - All Rights Reserved * (C) Copyright IBM Corp. 1998 - 2007 - All Rights Reserved
* *
*/ */
@ -34,6 +34,8 @@ le_uint32 CursiveAttachmentSubtable::process(GlyphIterator *glyphIterator, const
entryAnchorTable->getAnchor(glyphID, fontInstance, entryAnchor); entryAnchorTable->getAnchor(glyphID, fontInstance, entryAnchor);
glyphIterator->setCursiveEntryPoint(entryAnchor); glyphIterator->setCursiveEntryPoint(entryAnchor);
} else {
//glyphIterator->clearCursiveEntryPoint();
} }
if (exitOffset != 0) { if (exitOffset != 0) {
@ -41,6 +43,8 @@ le_uint32 CursiveAttachmentSubtable::process(GlyphIterator *glyphIterator, const
exitAnchorTable->getAnchor(glyphID, fontInstance, exitAnchor); exitAnchorTable->getAnchor(glyphID, fontInstance, exitAnchor);
glyphIterator->setCursiveExitPoint(exitAnchor); glyphIterator->setCursiveExitPoint(exitAnchor);
} else {
//glyphIterator->clearCursiveExitPoint();
} }
return 1; return 1;

View File

@ -1,6 +1,6 @@
/* /*
* *
* (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved * (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
* *
*/ */
@ -274,6 +274,36 @@ void GlyphIterator::setCurrGlyphPositionAdjustment(float xPlacementAdjust, float
glyphPositionAdjustments->setYAdvance(position, yAdvanceAdjust); glyphPositionAdjustments->setYAdvance(position, yAdvanceAdjust);
} }
void GlyphIterator::clearCursiveEntryPoint()
{
if (direction < 0) {
if (position <= nextLimit || position >= prevLimit) {
return;
}
} else {
if (position <= prevLimit || position >= nextLimit) {
return;
}
}
glyphPositionAdjustments->clearEntryPoint(position);
}
void GlyphIterator::clearCursiveExitPoint()
{
if (direction < 0) {
if (position <= nextLimit || position >= prevLimit) {
return;
}
} else {
if (position <= prevLimit || position >= nextLimit) {
return;
}
}
glyphPositionAdjustments->clearExitPoint(position);
}
void GlyphIterator::setCursiveEntryPoint(LEPoint &entryPoint) void GlyphIterator::setCursiveEntryPoint(LEPoint &entryPoint)
{ {
if (direction < 0) { if (direction < 0) {

View File

@ -1,6 +1,6 @@
/* /*
* *
* (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved * (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
* *
*/ */
@ -63,6 +63,8 @@ public:
void setCurrGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust, void setCurrGlyphPositionAdjustment(float xPlacementAdjust, float yPlacementAdjust,
float xAdvanceAdjust, float yAdvanceAdjust); float xAdvanceAdjust, float yAdvanceAdjust);
void clearCursiveEntryPoint();
void clearCursiveExitPoint();
void setCursiveEntryPoint(LEPoint &entryPoint); void setCursiveEntryPoint(LEPoint &entryPoint);
void setCursiveExitPoint(LEPoint &exitPoint); void setCursiveExitPoint(LEPoint &exitPoint);
void setCursiveGlyph(); void setCursiveGlyph();

View File

@ -1,6 +1,6 @@
/* /*
* *
* (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved * (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
* *
*/ */
@ -46,6 +46,20 @@ const LEPoint *GlyphPositionAdjustments::getExitPoint(le_int32 index, LEPoint &e
return fEntryExitPoints[index].getExitPoint(exitPoint); return fEntryExitPoints[index].getExitPoint(exitPoint);
} }
void GlyphPositionAdjustments::clearEntryPoint(le_int32 index)
{
CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount);
fEntryExitPoints[index].clearEntryPoint();
}
void GlyphPositionAdjustments::clearExitPoint(le_int32 index)
{
CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount);
fEntryExitPoints[index].clearExitPoint();
}
void GlyphPositionAdjustments::setEntryPoint(le_int32 index, LEPoint &newEntryPoint, le_bool baselineIsLogicalEnd) void GlyphPositionAdjustments::setEntryPoint(le_int32 index, LEPoint &newEntryPoint, le_bool baselineIsLogicalEnd)
{ {
CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount); CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount);

View File

@ -1,6 +1,6 @@
/* /*
* *
* (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved * (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
* *
*/ */
@ -72,6 +72,8 @@ private:
LEPoint *getEntryPoint(LEPoint &entryPoint) const; LEPoint *getEntryPoint(LEPoint &entryPoint) const;
LEPoint *getExitPoint(LEPoint &exitPoint) const; LEPoint *getExitPoint(LEPoint &exitPoint) const;
inline void clearEntryPoint();
inline void clearExitPoint();
inline void setEntryPoint(LEPoint &newEntryPoint, le_bool baselineIsLogicalEnd); inline void setEntryPoint(LEPoint &newEntryPoint, le_bool baselineIsLogicalEnd);
inline void setExitPoint(LEPoint &newExitPoint, le_bool baselineIsLogicalEnd); inline void setExitPoint(LEPoint &newExitPoint, le_bool baselineIsLogicalEnd);
inline void setCursiveGlyph(le_bool baselineIsLogicalEnd); inline void setCursiveGlyph(le_bool baselineIsLogicalEnd);
@ -126,6 +128,8 @@ public:
inline void adjustXAdvance(le_int32 index, float xAdjustment); inline void adjustXAdvance(le_int32 index, float xAdjustment);
inline void adjustYAdvance(le_int32 index, float yAdjustment); inline void adjustYAdvance(le_int32 index, float yAdjustment);
void clearEntryPoint(le_int32 index);
void clearExitPoint(le_int32 index);
void setEntryPoint(le_int32 index, LEPoint &newEntryPoint, le_bool baselineIsLogicalEnd); void setEntryPoint(le_int32 index, LEPoint &newEntryPoint, le_bool baselineIsLogicalEnd);
void setExitPoint(le_int32 index, LEPoint &newExitPoint, le_bool baselineIsLogicalEnd); void setExitPoint(le_int32 index, LEPoint &newExitPoint, le_bool baselineIsLogicalEnd);
void setCursiveGlyph(le_int32 index, le_bool baselineIsLogicalEnd); void setCursiveGlyph(le_int32 index, le_bool baselineIsLogicalEnd);
@ -241,6 +245,16 @@ inline le_bool GlyphPositionAdjustments::EntryExitPoint::baselineIsLogicalEnd()
return (fFlags & EEF_BASELINE_IS_LOGICAL_END) != 0; return (fFlags & EEF_BASELINE_IS_LOGICAL_END) != 0;
} }
inline void GlyphPositionAdjustments::EntryExitPoint::clearEntryPoint()
{
fFlags &= ~EEF_HAS_ENTRY_POINT;
}
inline void GlyphPositionAdjustments::EntryExitPoint::clearExitPoint()
{
fFlags &= ~EEF_HAS_EXIT_POINT;
}
inline void GlyphPositionAdjustments::EntryExitPoint::setEntryPoint(LEPoint &newEntryPoint, le_bool baselineIsLogicalEnd) inline void GlyphPositionAdjustments::EntryExitPoint::setEntryPoint(LEPoint &newEntryPoint, le_bool baselineIsLogicalEnd)
{ {
if (baselineIsLogicalEnd) { if (baselineIsLogicalEnd) {

View File

@ -1,6 +1,6 @@
/* /*
* *
* (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved * (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
* *
*/ */
@ -12,7 +12,10 @@
#endif #endif
#include "unicode/utypes.h" #include "unicode/utypes.h"
#ifdef XP_CPLUSPLUS
#include "unicode/uobject.h" #include "unicode/uobject.h"
#endif
#ifdef LE_USE_CMEMORY #ifdef LE_USE_CMEMORY
#include "cmemory.h" #include "cmemory.h"

View File

@ -26,6 +26,7 @@
#include "OpenTypeUtilities.h" #include "OpenTypeUtilities.h"
#include "GlyphSubstitutionTables.h" #include "GlyphSubstitutionTables.h"
#include "GlyphDefinitionTables.h"
#include "MorphTables.h" #include "MorphTables.h"
#include "DefaultCharMapper.h" #include "DefaultCharMapper.h"
@ -86,6 +87,37 @@ CharSubstitutionFilter::~CharSubstitutionFilter()
// nothing to do // nothing to do
} }
class CanonMarkFilter : public UMemory, public LEGlyphFilter
{
private:
const GlyphClassDefinitionTable *classDefTable;
CanonMarkFilter(const CanonMarkFilter &other); // forbid copying of this class
CanonMarkFilter &operator=(const CanonMarkFilter &other); // forbid copying of this class
public:
CanonMarkFilter(const GlyphDefinitionTableHeader *gdefTable);
virtual ~CanonMarkFilter();
virtual le_bool accept(LEGlyphID glyph) const;
};
CanonMarkFilter::CanonMarkFilter(const GlyphDefinitionTableHeader *gdefTable)
{
classDefTable = gdefTable->getMarkAttachClassDefinitionTable();
}
CanonMarkFilter::~CanonMarkFilter()
{
// nothing to do?
}
le_bool CanonMarkFilter::accept(LEGlyphID glyph) const
{
le_int32 glyphClass = classDefTable->getGlyphClass(glyph);
return glyphClass != 0;
}
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LayoutEngine) UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LayoutEngine)
@ -279,7 +311,7 @@ void LayoutEngine::positionGlyphs(LEGlyphStorage &glyphStorage, float x, float y
glyphStorage.setPosition(glyphCount, x, y, success); glyphStorage.setPosition(glyphCount, x, y, success);
} }
void LayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool /*reverse*/, void LayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse,
LEGlyphStorage &glyphStorage, LEErrorCode &success) LEGlyphStorage &glyphStorage, LEErrorCode &success)
{ {
if (LE_FAILURE(success)) { if (LE_FAILURE(success)) {
@ -291,6 +323,11 @@ void LayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset
return; return;
} }
GlyphDefinitionTableHeader *gdefTable = (GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable;
CanonMarkFilter filter(gdefTable);
adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
if (fTypoFlags & 0x1) { /* kerning enabled */ if (fTypoFlags & 0x1) { /* kerning enabled */
static const le_uint32 kernTableTag = LE_KERN_TABLE_TAG; static const le_uint32 kernTableTag = LE_KERN_TABLE_TAG;

View File

@ -1,6 +1,6 @@
#****************************************************************************** #******************************************************************************
# #
# Copyright (C) 1999-2006, International Business Machines # Copyright (C) 1999-2007, International Business Machines
# Corporation and others. All Rights Reserved. # Corporation and others. All Rights Reserved.
# #
#****************************************************************************** #******************************************************************************
@ -132,10 +132,11 @@ KhmerReordering.o \
TibetanLayoutEngine.o \ TibetanLayoutEngine.o \
TibetanReordering.o \ TibetanReordering.o \
HangulLayoutEngine.o \ HangulLayoutEngine.o \
KernTable.o KernTable.o \
loengine.o
## Header files to install ## Header files to install
HEADERS= $(srcdir)/LayoutEngine.h $(srcdir)/LE*.h HEADERS= $(srcdir)/LayoutEngine.h $(srcdir)/LE*.h $(srcdir)/loengine.h
STATIC_OBJECTS = $(OBJECTS:.o=.$(STATIC_O)) STATIC_OBJECTS = $(OBJECTS:.o=.$(STATIC_O))

View File

@ -332,6 +332,19 @@ void OpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int3
delete adjustments; delete adjustments;
} }
LEGlyphID zwnj = fFontInstance->mapCharToGlyph(0x200C);
LEGlyphID nbsp = fFontInstance->mapCharToGlyph(0x00A0);
for (le_int32 g = 0; g < glyphCount; g += 1) {
LEGlyphID glyph = glyphStorage[g];
if (glyph == zwnj) {
glyphStorage[g] = LE_SET_GLYPH(glyph, 0xFFFF);
} else if (glyph == nbsp) {
glyphStorage[g] = LE_SET_GLYPH(glyph, 0x0003);
}
}
#if 0 #if 0
// Don't know why this is here... // Don't know why this is here...
LE_DELETE_ARRAY(fFeatureTags); LE_DELETE_ARRAY(fFeatureTags);

View File

@ -369,6 +369,10 @@
RelativePath=".\LigatureSubstSubtables.cpp" RelativePath=".\LigatureSubstSubtables.cpp"
> >
</File> </File>
<File
RelativePath=".\loengine.cpp"
>
</File>
<File <File
RelativePath=".\LookupProcessor.cpp" RelativePath=".\LookupProcessor.cpp"
> >
@ -872,6 +876,19 @@
RelativePath=".\LigatureSubstSubtables.h" RelativePath=".\LigatureSubstSubtables.h"
> >
</File> </File>
<File
RelativePath=".\loengine.h"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\layout"
Outputs="..\..\include\layout\$(InputFileName)"
/>
</FileConfiguration>
</File>
<File <File
RelativePath=".\LookupProcessor.h" RelativePath=".\LookupProcessor.h"
> >

View File

@ -0,0 +1,163 @@
/*
*
* (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "loengine.h"
#include "LayoutEngine.h"
/**
* \file
* \brief C API for complex text layout.
*/
U_NAMESPACE_USE
U_CAPI le_engine * U_EXPORT2
le_create(const le_font *font,
le_int32 scriptCode,
le_int32 languageCode,
le_int32 typo_flags,
LEErrorCode *success)
{
LEFontInstance *fontInstance = (LEFontInstance *) font;
return (le_engine *) LayoutEngine::layoutEngineFactory(fontInstance, scriptCode, languageCode, typo_flags, *success);
}
U_CAPI void U_EXPORT2
le_close(le_engine *engine)
{
LayoutEngine *le = (LayoutEngine *) engine;
delete le;
}
U_CAPI le_int32 U_EXPORT2
le_layoutChars(le_engine *engine,
const LEUnicode chars[],
le_int32 offset,
le_int32 count,
le_int32 max,
le_bool rightToLeft,
float x,
float y,
LEErrorCode *success)
{
LayoutEngine *le = (LayoutEngine *) engine;
if (le == NULL) {
*success = LE_ILLEGAL_ARGUMENT_ERROR;
return -1;
}
return le->layoutChars(chars, offset, count, max, rightToLeft, x, y, *success);
}
U_CAPI le_int32 U_EXPORT2
le_getGlyphCount(le_engine *engine,
LEErrorCode *success)
{
LayoutEngine *le = (LayoutEngine *) engine;
if (le == NULL) {
*success = LE_ILLEGAL_ARGUMENT_ERROR;
return -1;
}
return le->getGlyphCount();
}
U_CAPI void U_EXPORT2
le_getGlyphs(le_engine *engine,
LEGlyphID glyphs[],
LEErrorCode *success)
{
LayoutEngine *le = (LayoutEngine *) engine;
if (le == NULL) {
*success = LE_ILLEGAL_ARGUMENT_ERROR;
return;
}
le->getGlyphs(glyphs, *success);
}
U_CAPI void U_EXPORT2
le_getCharIndices(le_engine *engine,
le_int32 charIndices[],
LEErrorCode *success)
{
LayoutEngine *le = (LayoutEngine *) engine;
if (le == NULL) {
*success = LE_ILLEGAL_ARGUMENT_ERROR;
return;
}
le->getCharIndices(charIndices, *success);
}
U_CAPI void U_EXPORT2
le_getCharIndicesWithBase(le_engine *engine,
le_int32 charIndices[],
le_int32 indexBase,
LEErrorCode *success)
{
LayoutEngine *le = (LayoutEngine *) engine;
if (le == NULL) {
*success = LE_ILLEGAL_ARGUMENT_ERROR;
return;
}
le->getCharIndices(charIndices, indexBase, *success);
}
U_CAPI void U_EXPORT2
le_getGlyphPositions(le_engine *engine,
float positions[],
LEErrorCode *success)
{
LayoutEngine *le = (LayoutEngine *) engine;
if (le == NULL) {
*success = LE_ILLEGAL_ARGUMENT_ERROR;
return;
}
le->getGlyphPositions(positions, *success);
}
U_CAPI void U_EXPORT2
le_getGlyphPosition(le_engine *engine,
le_int32 glyphIndex,
float *x,
float *y,
LEErrorCode *success)
{
LayoutEngine *le = (LayoutEngine *) engine;
if (le == NULL) {
*success = LE_ILLEGAL_ARGUMENT_ERROR;
return;
}
le->getGlyphPosition(glyphIndex, *x, *y, *success);
}
U_CAPI void U_EXPORT2
le_reset(le_engine *engine,
LEErrorCode *success)
{
LayoutEngine *le = (LayoutEngine *) engine;
if (le == NULL) {
*success = LE_ILLEGAL_ARGUMENT_ERROR;
return;
}
le->reset();
}

View File

@ -0,0 +1,223 @@
/*
*
* (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
*
*/
#ifndef __LOENGINE_H
#define __LOENGINE_H
#include "LETypes.h"
/**
* \file
* \brief C API for complex text layout.
* \internal
*
* This is a technology preview. The API may
* change significantly.
*
*/
/**
* The opaque type for a LayoutEngine.
*
* @internal
*/
typedef void le_engine;
/**
* The opaque type for a font instance.
*
* @internal
*/
typedef void le_font;
/**
* This function returns an le_engine capable of laying out text
* in the given font, script and langauge. Note that the LayoutEngine
* returned may be a subclass of LayoutEngine.
*
* @param font - the font of the text
* @param scriptCode - the script of the text
* @param languageCode - the language of the text
* @param typo_flags - flags that control layout features like kerning and ligatures.
* @param success - output parameter set to an error code if the operation fails
*
* @return an le_engine which can layout text in the given font.
*
* @internal
*/
U_DRAFT le_engine * U_EXPORT2
le_create(const le_font *font,
le_int32 scriptCode,
le_int32 languageCode,
le_int32 typo_flags,
LEErrorCode *success);
/**
* This function closes the given LayoutEngine. After
* it returns, the le_engine is no longer valid.
*
* @param engine - the LayoutEngine to close.
*
* @internal
*/
U_DRAFT void U_EXPORT2
le_close(le_engine *engine);
/**
* This routine will compute the glyph, character index and position arrays.
*
* @param engine - the LayoutEngine
* @param chars - the input character context
* @param offset - the offset of the first character to process
* @param count - the number of characters to process
* @param max - the number of characters in the input context
* @param rightToLeft - TRUE if the characers are in a right to left directional run
* @param x - the initial X position
* @param y - the initial Y position
* @param success - output parameter set to an error code if the operation fails
*
* @return the number of glyphs in the glyph array
*
* Note: The glyph, character index and position array can be accessed
* using the getter routines below.
*
* Note: If you call this function more than once, you must call the reset()
* function first to free the glyph, character index and position arrays
* allocated by the previous call.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
le_layoutChars(le_engine *engine,
const LEUnicode chars[],
le_int32 offset,
le_int32 count,
le_int32 max,
le_bool rightToLeft,
float x,
float y,
LEErrorCode *success);
/**
* This function returns the number of glyphs in the glyph array. Note
* that the number of glyphs will be greater than or equal to the number
* of characters used to create the LayoutEngine.
*
* @param engine - the LayoutEngine
* @param success - output parameter set to an error code if the operation fails.
*
* @return the number of glyphs in the glyph array
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
le_getGlyphCount(le_engine *engine,
LEErrorCode *success);
/**
* This function copies the glyph array into a caller supplied array.
* The caller must ensure that the array is large enough to hold all
* the glyphs.
*
* @param engine - the LayoutEngine
* @param glyphs - the destiniation glyph array
* @param success - set to an error code if the operation fails
*
* @internal
*/
U_DRAFT void U_EXPORT2
le_getGlyphs(le_engine *engine,
LEGlyphID glyphs[],
LEErrorCode *success);
/**
* This function copies the character index array into a caller supplied array.
* The caller must ensure that the array is large enough to hold a
* character index for each glyph.
*
* @param engine - the LayoutEngine
* @param charIndices - the destiniation character index array
* @param success - set to an error code if the operation fails
*
* @internal
*/
U_DRAFT void U_EXPORT2
le_getCharIndices(le_engine *engine,
le_int32 charIndices[],
LEErrorCode *success);
/**
* This function copies the character index array into a caller supplied array.
* The caller must ensure that the array is large enough to hold a
* character index for each glyph.
*
* @param engine - the LayoutEngine
* @param charIndices - the destiniation character index array
* @param indexBase - an offset that will be added to each index.
* @param success - set to an error code if the operation fails
*
* @internal
*/
U_DRAFT void U_EXPORT2
le_getCharIndicesWithBase(le_engine *engine,
le_int32 charIndices[],
le_int32 indexBase,
LEErrorCode *success);
/**
* This function copies the position array into a caller supplied array.
* The caller must ensure that the array is large enough to hold an
* X and Y position for each glyph, plus an extra X and Y for the
* advance of the last glyph.
*
* @param engine - the LayoutEngine
* @param positions - the destiniation position array
* @param success - set to an error code if the operation fails
*
* @internal
*/
U_DRAFT void U_EXPORT2
le_getGlyphPositions(le_engine *engine,
float positions[],
LEErrorCode *success);
/**
* This function returns the X and Y position of the glyph at
* the given index.
*
* Input parameters:
* @param engine - the LayoutEngine
* @param glyphIndex - the index of the glyph
*
* Output parameters:
* @param x - the glyph's X position
* @param y - the glyph's Y position
* @param success - set to an error code if the operation fails
*
* @internal
*/
U_DRAFT void U_EXPORT2
le_getGlyphPosition(le_engine *engine,
le_int32 glyphIndex,
float *x,
float *y,
LEErrorCode *success);
/**
* This function frees the glyph, character index and position arrays
* so that the LayoutEngine can be reused to layout a different
* characer array. (This function is also called by le_close)
*
* @param engine - the LayoutEngine
* @param success - set to an error code if the operation fails
*
* @internal
*/
U_DRAFT void U_EXPORT2
le_reset(le_engine *engine,
LEErrorCode *success);
#endif

View File

@ -1,6 +1,6 @@
#****************************************************************************** #******************************************************************************
# #
# Copyright (C) 1999-2005, International Business Machines # Copyright (C) 1999-2007, International Business Machines
# Corporation and others. All Rights Reserved. # Corporation and others. All Rights Reserved.
# #
#****************************************************************************** #******************************************************************************
@ -62,7 +62,9 @@ LIBS = $(LIBICUUC) $(LIBICULE) $(DEFAULT_LIBS)
OBJECTS = ParagraphLayout.o \ OBJECTS = ParagraphLayout.o \
RunArrays.o \ RunArrays.o \
LXUtilities.o LXUtilities.o \
playout.o \
plruns.o
## Header files to install ## Header files to install
HEADERS= $(srcdir)/layout/ParagraphLayout.h $(srcdir)/layout/RunArrays.h HEADERS= $(srcdir)/layout/ParagraphLayout.h $(srcdir)/layout/RunArrays.h

View File

@ -1,6 +1,6 @@
/* /*
********************************************************************** **********************************************************************
* Copyright (C) 2003-2005, International Business Machines * Copyright (C) 2003-2007, International Business Machines
* Corporation and others. All Rights Reserved. * Corporation and others. All Rights Reserved.
********************************************************************** **********************************************************************
*/ */
@ -502,6 +502,8 @@ protected:
virtual void init(le_int32 capacity); virtual void init(le_int32 capacity);
virtual void grow(le_int32 capacity); virtual void grow(le_int32 capacity);
const Locale **fLocales;
private: private:
inline LocaleRuns(); inline LocaleRuns();
@ -513,8 +515,6 @@ private:
* for ICU "poor man's RTTI". * for ICU "poor man's RTTI".
*/ */
static const char fgClassID; static const char fgClassID;
const Locale **fLocales;
}; };
inline LocaleRuns::LocaleRuns() inline LocaleRuns::LocaleRuns()

View File

@ -0,0 +1,458 @@
/*
*
* (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
*
*/
#ifndef __PLAYOUT_H
#define __PLAYOUT_H
#include "unicode/ubidi.h"
#include "layout/LETypes.h"
#include "plruns.h"
/**
* \file
* \brief C API for paragraph layout.
* \internal
*
* This is a technology preview. The API may
* change significantly.
*
*/
/**
* The opaque type for a paragraph layout.
*
* @internal
*/
typedef void pl_paragraph;
/**
* The opaque type for a line in a paragraph layout.
*
* @internal
*/
typedef void pl_line;
/**
* The opaque type for a visual run in a line.
*
* @internal
*/
typedef void pl_visualRun;
/**
* Construct a <code>ParagraphLayout</code> object for a styled paragraph. The paragraph is specified
* as runs of text all in the same font. An <code>LEFontInstance</code> object and a limit offset
* are specified for each font run. The limit offset is the offset of the character immediately
* after the font run.
*
* Clients can optionally specify directional runs and / or script runs. If these aren't specified
* they will be computed.
*
* If any errors are encountered during construction, <code>status</code> will be set, and the object
* will be set to be empty.
*
* @param chars is an array of the characters in the paragraph
*
* @param count is the number of characters in the paragraph.
*
* @param fontRuns a pointer to a <code>pl_fontRuns</code> object representing the font runs.
*
* @param levelRuns is a pointer to a <code>pl_valueRuns</code> object representing the directional levels.
* If this pointer in <code>NULL</code> the levels will be determined by running the Unicde
* Bidi algorithm.
*
* @param scriptRuns is a pointer to a <code>pl_valueRuns</code> object representing script runs.
* If this pointer in <code>NULL</code> the script runs will be determined using the
* Unicode code points.
*
* @param localeRuns is a pointer to a <code>pl_localeRuns</code> object representing locale runs.
* The <code>Locale</code> objects are used to determind the language of the text. If this
* pointer is <code>NULL</code> the default locale will be used for all of the text.
*
* @param paragraphLevel is the directionality of the paragraph, as in the UBiDi object.
*
* @param vertical is <code>TRUE</code> if the paragraph should be set vertically.
*
* @param status will be set to any error code encountered during construction.
*
* @return a pointer to the newly created <code>pl_paragraph</code> object. The object
* will remain valid until <code>pl_close</code> is called.
*
* @see ubidi.h
* @see longine.h
* @see plruns.h
*
* @internal
*/
U_DRAFT pl_paragraph * U_EXPORT2
pl_create(const LEUnicode chars[],
le_int32 count,
const pl_fontRuns *fontRuns,
const pl_valueRuns *levelRuns,
const pl_valueRuns *scriptRuns,
const pl_localeRuns *localeRuns,
UBiDiLevel paragraphLevel,
le_bool vertical,
LEErrorCode *status);
/**
* Close the given paragraph layout object.
*
* @param paragraph the <code>pl_paragraph</code> object to be
* closed. Once this routine returns the object
* can no longer be referenced
*
* @internal
*/
U_DRAFT void U_EXPORT2
pl_close(pl_paragraph *paragraph);
/**
* Examine the given text and determine if it contains characters in any
* script which requires complex processing to be rendered correctly.
*
* @param chars is an array of the characters in the paragraph
*
* @param count is the number of characters in the paragraph.
*
* @return <code>TRUE</code> if any of the text requires complex processing.
*
* @internal
*/
U_DRAFT le_bool U_EXPORT2
pl_isComplex(const LEUnicode chars[],
le_int32 count);
/**
* Return the resolved paragraph level. This is useful for those cases
* where the bidi analysis has determined the level based on the first
* strong character in the paragraph.
*
* @param paragraph the <code>pl_paragraph</code>
*
* @return the resolved paragraph level.
*
* @internal
*/
U_DRAFT UBiDiLevel U_EXPORT2
pl_getParagraphLevel(pl_paragraph *paragraph);
/**
* Return the directionality of the text in the paragraph.
*
* @param paragraph the <code>pl_paragraph</code>
*
* @return <code>UBIDI_LTR</code> if the text is all left to right,
* <code>UBIDI_RTL</code> if the text is all right to left,
* or <code>UBIDI_MIXED</code> if the text has mixed direction.
*
* @internal
*/
U_DRAFT UBiDiDirection U_EXPORT2
pl_getTextDirection(pl_paragraph *paragraph);
/**
* Get the max ascent value for all the fonts
* in the paragraph.
*
* @param paragraph the <code>pl_paragraph</code>
*
* Return the max ascent value for all the fonts
* in the paragraph.
*
* @param paragraph the <code>pl_paragraph</code>
*
* @return the ascent value.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_getAscent(const pl_paragraph *paragraph);
/**
* Return the max descent value for all the fonts
* in the paragraph.
*
* @param paragraph the <code>pl_paragraph</code>
*
* @return the decent value.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_getDescent(const pl_paragraph *paragraph);
/**
* Return the max leading value for all the fonts
* in the paragraph.
*
* @param paragraph the <code>pl_paragraph</code>
*
* @return the leading value.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_getLeading(const pl_paragraph *paragraph);
/**
* Reset line breaking to start from the beginning of the paragraph.
*
* @param paragraph the <code>pl_paragraph</code>
*
* @internal
*/
U_DRAFT void U_EXPORT2
pl_reflow(pl_paragraph *paragraph);
/**
* Return a <code>pl_line</code> object which represents next line
* in the paragraph. The width of the line is specified each time so that it can
* be varied to support arbitrary paragraph shapes.
*
* @param paragraph the <code>pl_paragraph</code>
* @param width is the width of the line. If <code>width</code> is less than or equal
* to zero, a <code>ParagraphLayout::Line</code> object representing the
* rest of the paragraph will be returned.
*
* @return a <code>ParagraphLayout::Line</code> object which represents the line. The caller
* is responsible for deleting the object. Returns <code>NULL</code> if there are no
* more lines in the paragraph.
*
* @see pl_line
*
* @internal
*/
U_DRAFT pl_line * U_EXPORT2
pl_nextLine(pl_paragraph *paragraph, float width);
/**
* Close the given line object. Line objects are created
* by <code>pl_nextLine</code> but it is the client's responsibility
* to close them by calling this routine.
*
* @param line the <code>pl_line</code> object to close.
*
* @internal
*/
U_DRAFT void U_EXPORT2
pl_closeLine(pl_line *line);
/**
* Count the number of visual runs in the line.
*
* @param line the <code>pl_line</code> object.
*
* @return the number of visual runs.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_countLineRuns(const pl_line *line);
/**
* Get the ascent of the line. This is the maximum ascent
* of all the fonts on the line.
*
* @param line the <code>pl_line</code> object.
*
* @return the ascent of the line.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_getLineAscent(const pl_line *line);
/**
* Get the descent of the line. This is the maximum descent
* of all the fonts on the line.
*
* @param line the <code>pl_line</code> object.
*
* @return the descent of the line.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_getLineDescent(const pl_line *line);
/**
* Get the leading of the line. This is the maximum leading
* of all the fonts on the line.
*
* @param line the <code>pl_line</code> object.
*
* @return the leading of the line.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_getLineLeading(const pl_line *line);
/**
* Get the width of the line. This is a convenience method
* which returns the last X position of the last visual run
* in the line.
*
* @param line the <code>pl_line</code> object.
*
* @return the width of the line.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_getLineWidth(const pl_line *line);
/**
* Get a <code>ParagraphLayout::VisualRun</code> object for a given
* visual run in the line.
*
* @param line the <code>pl_line</code> object.
* @param runIndex is the index of the run, in visual order.
*
* @return the <code>pl_visualRun</code> object representing the
* visual run. This object is owned by the <code>pl_line</code> object which
* created it, and will remain valid for as long as the <code>pl_line</code>
* object is valid.
*
* @see pl_visualRun
*
* @internal
*/
U_DRAFT const pl_visualRun * U_EXPORT2
pl_getLineVisualRun(const pl_line *line, le_int32 runIndex);
/**
* Get the <code>le_font</code> object which
* represents the font of the visual run. This will always
* be a non-composite font.
*
* @param run the <code>pl_visualRun</code> object.
*
* @return the <code>le_font</code> object which represents the
* font of the visual run.
*
* @see le_font
*
* @internal
*/
U_DRAFT const le_font * U_EXPORT2
pl_getVisualRunFont(const pl_visualRun *run);
/**
* Get the direction of the visual run.
*
* @param run the <code>pl_visualRun</code> object.
*
* @return the direction of the run. This will be <code>UBIDI_LTR</code> if the
* run is left-to-right and <code>UBIDI_RTL</code> if the line is right-to-left.
*
* @internal
*/
U_DRAFT UBiDiDirection U_EXPORT2
pl_getVisualRunDirection(const pl_visualRun *run);
/**
* Get the number of glyphs in the visual run.
*
* @param run the <code>pl_visualRun</code> object.
*
* @return the number of glyphs.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_getVisualRunGlyphCount(const pl_visualRun *run);
/**
* Get the glyphs in the visual run. Glyphs with the values <code>0xFFFE</code> and
* <code>0xFFFF</code> should be ignored.
*
* @param run the <code>pl_visualRun</code> object.
*
* @return the address of the array of glyphs for this visual run. The storage
* is owned by the <code>pl_visualRun</code> object and must not be deleted.
* It will remain valid as long as the <code>pl_visualRun</code> object is valid.
*
* @internal
*/
U_DRAFT const LEGlyphID * U_EXPORT2
pl_getVisualRunGlyphs(const pl_visualRun *run);
/**
* Get the (x, y) positions of the glyphs in the visual run. To simplify storage
* management, the x and y positions are stored in a single array with the x positions
* at even offsets in the array and the corresponding y position in the following odd offset.
* There is an extra (x, y) pair at the end of the array which represents the advance of
* the final glyph in the run.
*
* @param run the <code>pl_visualRun</code> object.
*
* @return the address of the array of glyph positions for this visual run. The storage
* is owned by the <code>pl_visualRun</code> object and must not be deleted.
* It will remain valid as long as the <code>pl_visualRun</code> object is valid.
*
* @internal
*/
U_DRAFT const float * U_EXPORT2
pl_getVisualRunPositions(const pl_visualRun *run);
/**
* Get the glyph-to-character map for this visual run. This maps the indices into
* the glyph array to indices into the character array used to create the paragraph.
*
* @param run the <code>pl_visualRun</code> object.
*
* @return the address of the character-to-glyph map for this visual run. The storage
* is owned by the <code>pl_visualRun</code> object and must not be deleted.
* It will remain valid as long as the <code>pl_visualRun</code> object is valid.
*
* @internal
*/
U_DRAFT const le_int32 * U_EXPORT2
pl_getVisualRunGlyphToCharMap(const pl_visualRun *run);
/**
* A convenience method which returns the ascent value for the font
* associated with this run.
*
* @param run the <code>pl_visualRun</code> object.
*
* @return the ascent value of this run's font.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_getVisualRunAscent(const pl_visualRun *run);
/**
* A convenience method which returns the descent value for the font
* associated with this run.
*
* @param run the <code>pl_visualRun</code> object.
*
* @return the descent value of this run's font.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_getVisualRunDescent(const pl_visualRun *run);
/**
* A convenience method which returns the leading value for the font
* associated with this run.
*
* @param run the <code>pl_visualRun</code> object.
*
* @return the leading value of this run's font.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_getVisualRunLeading(const pl_visualRun *run);
#endif

View File

@ -0,0 +1,429 @@
/*
*
* (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
*
*/
#ifndef __PLRUNS_H
#define __PLRUNS_H
#include "unicode/utypes.h"
#include "unicode/ubidi.h"
#include "layout/LETypes.h"
#include "layout/loengine.h"
typedef void pl_fontRuns;
typedef void pl_valueRuns;
typedef void pl_localeRuns;
/**
* \file
* \brief C API for run arrays.
* \internal
*
* This is a technology preview. The API may
* change significantly.
*
*/
/**
* Construct a <code>pl_fontRuns</code> object from pre-existing arrays of fonts
* and limit indices.
*
* @param fonts is the address of an array of pointers to <code>le_font</code> objects. This
* array, and the <code>le_font</code> objects to which it points must remain
* valid until the <code>pl_fontRuns</code> object is closed.
*
* @param limits is the address of an array of limit indices. This array must remain valid until
* the <code>pl_fontRuns</code> object is closed.
*
* @param count is the number of entries in the two arrays.
*
* @internal
*/
U_DRAFT pl_fontRuns * U_EXPORT2
pl_openFontRuns(const le_font **fonts,
const le_int32 *limits,
le_int32 count);
/**
* Construct an empty <code>pl_fontRuns</code> object. Clients can add font and limit
* indices arrays using the <code>pl_addFontRun</code> routine.
*
* @param initialCapacity is the initial size of the font and limit indices arrays. If
* this value is zero, no arrays will be allocated.
*
* @see pl_addFontRun
*
* @internal
*/
U_DRAFT pl_fontRuns * U_EXPORT2
pl_openEmptyFontRuns(le_int32 initialCapacity);
/**
* Close the given <code>pl_fontRuns</code> object. Once this
* call returns, the object can no longer be referenced.
*
* @param fontRuns is the <code>pl_fontRuns</code> object.
*
* @internal
*/
U_DRAFT void U_EXPORT2
pl_closeFontRuns(pl_fontRuns *fontRuns);
/**
* Get the number of font runs.
*
* @param fontRuns is the <code>pl_fontRuns</code> object.
*
* @return the number of entries in the limit indices array.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_getFontRunCount(const pl_fontRuns *fontRuns);
/**
* Reset the number of font runs to zero.
*
* @param fontRuns is the <code>pl_fontRuns</code> object.
*
* @internal
*/
U_DRAFT void U_EXPORT2
pl_resetFontRuns(pl_fontRuns *fontRuns);
/**
* Get the limit index for the last font run. This is the
* number of characters in the text.
*
* @param fontRuns is the <code>pl_fontRuns</code> object.
*
* @return the last limit index.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_getFontRunLastLimit(const pl_fontRuns *fontRuns);
/**
* Get the limit index for a particular font run.
*
* @param fontRuns is the <code>pl_fontRuns</code> object.
* @param run is the run. This is an index into the limit index array.
*
* @return the limit index for the run, or -1 if <code>run</code> is out of bounds.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_getFontRunLimit(const pl_fontRuns *fontRuns,
le_int32 run);
/**
* Get the <code>le_font</code> object assoicated with the given run
* of text. Use <code>pl_getFontRunLimit(run)</code> to get the corresponding
* limit index.
*
* @param fontRuns is the <code>pl_fontRuns</code> object.
* @param run is the index into the font and limit indices arrays.
*
* @return the <code>le_font</code> associated with the given text run.
*
* @internal
*/
U_DRAFT const le_font * U_EXPORT2
pl_getFontRunFont(const pl_fontRuns *fontRuns,
le_int32 run);
/**
* Add a new font run to the given <code>pl_fontRuns</code> object.
*
* If the <code>pl_fontRuns</code> object was not created by calling
* <code>pl_openEmptyFontRuns</code>, this method will return a run index of -1.
*
* @param fontRuns is the <code>pl_fontRuns</code> object.
*
* @param font is the address of the <code>le_font</code> to add. This object must
* remain valid until the <code>pl_fontRuns</code> object is closed.
*
* @param limit is the limit index to add
*
* @return the run index where the font and limit index were stored, or -1 if
* the run cannot be added.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_addFontRun(pl_fontRuns *fontRuns,
const le_font *font,
le_int32 limit);
/**
* Construct a <code>pl_valueRuns</code> object from pre-existing arrays of values
* and limit indices.
*
* @param values is the address of an array of values. This array must remain valid until
the <code>pl_valueRuns</code> object is closed.
*
* @param limits is the address of an array of limit indices. This array must remain valid until
* the <code>pl_valueRuns</code> object is closed.
*
* @param count is the number of entries in the two arrays.
*
* @internal
*/
U_DRAFT pl_valueRuns * U_EXPORT2
pl_openValueRuns(const le_int32 *values,
const le_int32 *limits,
le_int32 count);
/**
* Construct an empty <code>pl_valueRuns</code> object. Clients can add values and limits
* using the <code>pl_addValueRun</code> routine.
*
* @param initialCapacity is the initial size of the value and limit indices arrays. If
* this value is zero, no arrays will be allocated.
*
* @see pl_addValueRun
*
* @internal
*/
U_DRAFT pl_valueRuns * U_EXPORT2
pl_openEmptyValueRuns(le_int32 initialCapacity);
/**
* Close the given <code>pl_valueRuns</code> object. Once this
* call returns, the object can no longer be referenced.
*
* @param valueRuns is the <code>pl_valueRuns</code> object.
*
* @internal
*/
U_DRAFT void U_EXPORT2
pl_closeValueRuns(pl_valueRuns *valueRuns);
/**
* Get the number of value runs.
*
* @param valueRuns is the <code>pl_valueRuns</code> object.
*
* @return the number of value runs.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_getValueRunCount(const pl_valueRuns *valueRuns);
/**
* Reset the number of value runs to zero.
*
* @param valueRuns is the <code>pl_valueRuns</code> object.
*
* @internal
*/
U_DRAFT void U_EXPORT2
pl_resetValueRuns(pl_valueRuns *valueRuns);
/**
* Get the limit index for the last value run. This is the
* number of characters in the text.
*
* @param valuetRuns is the <code>pl_valueRuns</code> object.
*
* @return the last limit index.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_getValueRunLastLimit(const pl_valueRuns *valueRuns);
/**
* Get the limit index for a particular value run.
*
* @param valueRuns is the <code>pl_valueRuns</code> object.
* @param run is the run index.
*
* @return the limit index for the run, or -1 if <code>run</code> is out of bounds.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_getValueRunLimit(const pl_valueRuns *valueRuns,
le_int32 run);
/**
* Get the value assoicated with the given run * of text. Use
* <code>pl_getValueRunLimit(run)</code> to get the corresponding
* limit index.
*
* @param valueRuns is the <code>pl_valueRuns</code> object.
* @param run is the run index.
*
* @return the value associated with the given text run.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_getValueRunValue(const pl_valueRuns *valueRuns,
le_int32 run);
/**
* Add a new font run to the given <code>pl_valueRuns</code> object.
*
* If the <code>pl_valueRuns</code> object was not created by calling
* <code>pl_openEmptyFontRuns</code>, this method will return a run index of -1.
*
* @param valueRuns is the <code>pl_valueRuns</code> object.
*
* @param value is the value to add.
*
* @param limit is the limit index to add
*
* @return the run index where the font and limit index were stored, or -1 if
* the run cannot be added.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_addValueRun(pl_valueRuns *valueRuns,
le_int32 value,
le_int32 limit);
/**
* Construct a <code>pl_localeRuns</code> object from pre-existing arrays of fonts
* and limit indices.
*
* @param locales is the address of an array of pointers to locale name strings. This
* array must remain valid until the <code>pl_localeRuns</code> object is destroyed.
*
* @param limits is the address of an array of limit indices. This array must remain valid until
* the <code>pl_valueRuns</code> object is destroyed.
*
* @param count is the number of entries in the two arrays.
*
* @internal
*/
U_DRAFT pl_localeRuns * U_EXPORT2
pl_openLocaleRuns(const char **locales,
const le_int32 *limits,
le_int32 count);
/**
* Construct an empty <code>pl_localeRuns</code> object. Clients can add font and limit
* indices arrays using the <code>pl_addFontRun</code> routine.
*
* @param initialCapacity is the initial size of the font and limit indices arrays. If
* this value is zero, no arrays will be allocated.
*
* @see pl_addLocaleRun
*
* @internal
*/
U_DRAFT pl_localeRuns * U_EXPORT2
pl_openEmptyLocaleRuns(le_int32 initialCapacity);
/**
* Close the given <code>pl_localeRuns</code> object. Once this
* call returns, the object can no longer be referenced.
*
* @param localeRuns is the <code>pl_localeRuns</code> object.
*
* @internal
*/
U_DRAFT void U_EXPORT2
pl_closeLocaleRuns(pl_localeRuns *localeRuns);
/**
* Get the number of font runs.
*
* @param localeRuns is the <code>pl_localeRuns</code> object.
*
* @return the number of entries in the limit indices array.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_getLocaleRunCount(const pl_localeRuns *localeRuns);
/**
* Reset the number of locale runs to zero.
*
* @param localeRuns is the <code>pl_localeRuns</code> object.
*
* @internal
*/
U_DRAFT void U_EXPORT2
pl_resetLocaleRuns(pl_localeRuns *localeRuns);
/**
* Get the limit index for the last font run. This is the
* number of characters in the text.
*
* @param localeRuns is the <code>pl_localeRuns</code> object.
*
* @return the last limit index.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_getLocaleRunLastLimit(const pl_localeRuns *localeRuns);
/**
* Get the limit index for a particular font run.
*
* @param localeRuns is the <code>pl_localeRuns</code> object.
* @param run is the run. This is an index into the limit index array.
*
* @return the limit index for the run, or -1 if <code>run</code> is out of bounds.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_getLocaleRunLimit(const pl_localeRuns *localeRuns,
le_int32 run);
/**
* Get the <code>le_font</code> object assoicated with the given run
* of text. Use <code>pl_getLocaleRunLimit(run)</code> to get the corresponding
* limit index.
*
* @param localeRuns is the <code>pl_localeRuns</code> object.
* @param run is the index into the font and limit indices arrays.
*
* @return the <code>le_font</code> associated with the given text run.
*
* @internal
*/
U_DRAFT const char * U_EXPORT2
pl_getLocaleRunLocale(const pl_localeRuns *localeRuns,
le_int32 run);
/**
* Add a new run to the given <code>pl_localeRuns</code> object.
*
* If the <code>pl_localeRuns</code> object was not created by calling
* <code>pl_openEmptyLocaleRuns</code>, this method will return a run index of -1.
*
* @param localeRuns is the <code>pl_localeRuns</code> object.
*
* @param locale is the name of the locale to add. This name must
* remain valid until the <code>pl_localeRuns</code> object is closed.
*
* @param limit is the limit index to add
*
* @return the run index where the font and limit index were stored, or -1 if
* the run cannot be added.
*
* @internal
*/
U_DRAFT le_int32 U_EXPORT2
pl_addLocaleRun(pl_localeRuns *localeRuns,
const char *locale,
le_int32 limit);
#endif

View File

@ -4,6 +4,7 @@
Version="8.00" Version="8.00"
Name="layoutex" Name="layoutex"
ProjectGUID="{37FC2C7F-1904-4811-8955-2F478830EAD1}" ProjectGUID="{37FC2C7F-1904-4811-8955-2F478830EAD1}"
RootNamespace="layoutex"
> >
<Platforms> <Platforms>
<Platform <Platform
@ -219,6 +220,14 @@
RelativePath=".\ParagraphLayout.cpp" RelativePath=".\ParagraphLayout.cpp"
> >
</File> </File>
<File
RelativePath=".\playout.cpp"
>
</File>
<File
RelativePath=".\plruns.cpp"
>
</File>
<File <File
RelativePath=".\RunArrays.cpp" RelativePath=".\RunArrays.cpp"
> >
@ -254,6 +263,32 @@
/> />
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\layout\playout.h"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\layout"
Outputs="..\..\include\layout\$(InputFileName)"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\layout\plruns.h"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\layout"
Outputs="..\..\include\layout\$(InputFileName)"
/>
</FileConfiguration>
</File>
<File <File
RelativePath=".\layout\RunArrays.h" RelativePath=".\layout\RunArrays.h"
> >

View File

@ -0,0 +1,323 @@
/*
*
* (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
*
*/
#include "layout/LETypes.h"
#include "layout/loengine.h"
#include "layout/plruns.h"
#include "layout/playout.h"
#include "unicode/locid.h"
#include "layout/LayoutEngine.h"
#include "layout/ParagraphLayout.h"
U_NAMESPACE_USE
U_CAPI pl_paragraph * U_EXPORT2
pl_create(const LEUnicode chars[],
le_int32 count,
const pl_fontRuns *fontRuns,
const pl_valueRuns *levelRuns,
const pl_valueRuns *scriptRuns,
const pl_localeRuns *localeRuns,
UBiDiLevel paragraphLevel,
le_bool vertical,
LEErrorCode *status)
{
ParagraphLayout *pl = new ParagraphLayout(chars, count, (const FontRuns *) fontRuns,
(const ValueRuns *) levelRuns, (const ValueRuns *) scriptRuns, (const LocaleRuns *) localeRuns,
paragraphLevel, vertical, *status);
return (pl_paragraph *) pl;
}
U_CAPI void U_EXPORT2
pl_close(pl_paragraph *paragraph)
{
ParagraphLayout *pl = (ParagraphLayout *) paragraph;
delete pl;
}
U_CAPI le_bool U_EXPORT2
pl_isComplex(const LEUnicode chars[],
le_int32 count)
{
return ParagraphLayout::isComplex(chars, count);
}
U_CAPI UBiDiLevel U_EXPORT2
pl_getParagraphLevel(pl_paragraph *paragraph)
{
ParagraphLayout *pl = (ParagraphLayout *) paragraph;
if (pl == NULL) {
return 0;
}
return pl->getParagraphLevel();
}
U_CAPI UBiDiDirection U_EXPORT2
pl_getTextDirection(pl_paragraph *paragraph)
{
ParagraphLayout *pl = (ParagraphLayout *) paragraph;
if (pl == NULL) {
return UBIDI_LTR;
}
return pl->getTextDirection();
}
U_CAPI le_int32 U_EXPORT2
pl_getAscent(const pl_paragraph *paragraph)
{
ParagraphLayout *pl = (ParagraphLayout *) paragraph;
if (pl == NULL) {
return 0;
}
return pl->getAscent();
}
U_CAPI le_int32 U_EXPORT2
pl_getDescent(const pl_paragraph *paragraph)
{
ParagraphLayout *pl = (ParagraphLayout *) paragraph;
if (pl == NULL) {
return 0;
}
return pl->getDescent();
}
U_CAPI le_int32 U_EXPORT2
pl_getLeading(const pl_paragraph *paragraph)
{
ParagraphLayout *pl = (ParagraphLayout *) paragraph;
if (pl == NULL) {
return 0;
}
return pl->getLeading();
}
U_CAPI void U_EXPORT2
pl_reflow(pl_paragraph *paragraph)
{
ParagraphLayout *pl = (ParagraphLayout *) paragraph;
if (pl == NULL) {
return;
}
return pl->reflow();
}
U_CAPI pl_line * U_EXPORT2
pl_nextLine(pl_paragraph *paragraph, float width)
{
ParagraphLayout *pl = (ParagraphLayout *) paragraph;
if (pl == NULL) {
return NULL;
}
return (pl_line *) pl->nextLine(width);
}
U_CAPI void U_EXPORT2
pl_closeLine(pl_line *line)
{
ParagraphLayout::Line *ll = (ParagraphLayout::Line *) line;
delete ll;
}
U_CAPI le_int32 U_EXPORT2
pl_countLineRuns(const pl_line *line)
{
ParagraphLayout::Line *ll = (ParagraphLayout::Line *) line;
if (ll == NULL) {
return 0;
}
return ll->countRuns();
}
U_CAPI le_int32 U_EXPORT2
pl_getLineAscent(const pl_line *line)
{
ParagraphLayout::Line *ll = (ParagraphLayout::Line *) line;
if (ll == NULL) {
return 0;
}
return ll->getAscent();
}
U_CAPI le_int32 U_EXPORT2
pl_getLineDescent(const pl_line *line)
{
ParagraphLayout::Line *ll = (ParagraphLayout::Line *) line;
if (ll == NULL) {
return 0;
}
return ll->getDescent();
}
U_CAPI le_int32 U_EXPORT2
pl_getLineLeading(const pl_line *line)
{
ParagraphLayout::Line *ll = (ParagraphLayout::Line *) line;
if (ll == NULL) {
return 0;
}
return ll->getLeading();
}
U_CAPI le_int32 U_EXPORT2
pl_getLineWidth(const pl_line *line)
{
ParagraphLayout::Line *ll = (ParagraphLayout::Line *) line;
if (ll == NULL) {
return 0;
}
return ll->getWidth();
}
U_CAPI const pl_visualRun * U_EXPORT2
pl_getLineVisualRun(const pl_line *line, le_int32 runIndex)
{
ParagraphLayout::Line *ll = (ParagraphLayout::Line *) line;
if (ll == NULL) {
return 0;
}
return (pl_visualRun *) ll->getVisualRun(runIndex);
}
U_CAPI const le_font * U_EXPORT2
pl_getVisualRunFont(const pl_visualRun *run)
{
ParagraphLayout::VisualRun *vr = (ParagraphLayout::VisualRun *) run;
if (vr == NULL) {
return NULL;
}
return (const le_font *) vr->getFont();
}
U_CAPI UBiDiDirection U_EXPORT2
pl_getVisualRunDirection(const pl_visualRun *run)
{
ParagraphLayout::VisualRun *vr = (ParagraphLayout::VisualRun *) run;
if (vr == NULL) {
return UBIDI_LTR;
}
return vr->getDirection();
}
U_CAPI le_int32 U_EXPORT2
pl_getVisualRunGlyphCount(const pl_visualRun *run)
{
ParagraphLayout::VisualRun *vr = (ParagraphLayout::VisualRun *) run;
if (vr == NULL) {
return -1;
}
return vr->getGlyphCount();
}
U_CAPI const LEGlyphID * U_EXPORT2
pl_getVisualRunGlyphs(const pl_visualRun *run)
{
ParagraphLayout::VisualRun *vr = (ParagraphLayout::VisualRun *) run;
if (vr == NULL) {
return NULL;
}
return vr->getGlyphs();
}
U_CAPI const float * U_EXPORT2
pl_getVisualRunPositions(const pl_visualRun *run)
{
ParagraphLayout::VisualRun *vr = (ParagraphLayout::VisualRun *) run;
if (vr == NULL) {
return NULL;
}
return vr->getPositions();
}
U_CAPI const le_int32 * U_EXPORT2
pl_getVisualRunGlyphToCharMap(const pl_visualRun *run)
{
ParagraphLayout::VisualRun *vr = (ParagraphLayout::VisualRun *) run;
if (vr == NULL) {
return NULL;
}
return vr->getGlyphToCharMap();
}
U_CAPI le_int32 U_EXPORT2
pl_getVisualRunAscent(const pl_visualRun *run)
{
ParagraphLayout::VisualRun *vr = (ParagraphLayout::VisualRun *) run;
if (vr == NULL) {
return 0;
}
return vr->getAscent();
}
U_CAPI le_int32 U_EXPORT2
pl_getVisualRunDescent(const pl_visualRun *run)
{
ParagraphLayout::VisualRun *vr = (ParagraphLayout::VisualRun *) run;
if (vr == NULL) {
return 0;
}
return vr->getDescent();
}
U_CAPI le_int32 U_EXPORT2
pl_getVisualRunLeading(const pl_visualRun *run)
{
ParagraphLayout::VisualRun *vr = (ParagraphLayout::VisualRun *) run;
if (vr == NULL) {
return 0;
}
return vr->getLeading();
}

View File

@ -0,0 +1,508 @@
/*
*
* (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
*
*/
#include "layout/LETypes.h"
#include "layout/loengine.h"
#include "layout/plruns.h"
#include "unicode/locid.h"
#include "layout/LayoutEngine.h"
#include "layout/RunArrays.h"
U_NAMESPACE_USE
U_CAPI pl_fontRuns * U_EXPORT2
pl_openFontRuns(const le_font **fonts,
const le_int32 *limits,
le_int32 count)
{
return (pl_fontRuns *) new FontRuns((const LEFontInstance **) fonts, limits, count);
}
U_CAPI pl_fontRuns * U_EXPORT2
pl_openEmptyFontRuns(le_int32 initialCapacity)
{
return (pl_fontRuns *) new FontRuns(initialCapacity);
}
U_CAPI void U_EXPORT2
pl_closeFontRuns(pl_fontRuns *fontRuns)
{
FontRuns *fr = (FontRuns *) fontRuns;
delete fr;
}
U_CAPI le_int32 U_EXPORT2
pl_getFontRunCount(const pl_fontRuns *fontRuns)
{
const FontRuns *fr = (const FontRuns *) fontRuns;
if (fr == NULL) {
return -1;
}
return fr->getCount();
}
U_CAPI void U_EXPORT2
pl_resetFontRuns(pl_fontRuns *fontRuns)
{
FontRuns *fr = (FontRuns *) fontRuns;
if (fr != NULL) {
fr->reset();
}
}
U_CAPI le_int32 U_EXPORT2
pl_getFontRunLastLimit(const pl_fontRuns *fontRuns)
{
const FontRuns *fr = (const FontRuns *) fontRuns;
if (fr == NULL) {
return -1;
}
return fr->getLimit();
}
U_CAPI le_int32 U_EXPORT2
pl_getFontRunLimit(const pl_fontRuns *fontRuns,
le_int32 run)
{
const FontRuns *fr = (const FontRuns *) fontRuns;
if (fr == NULL) {
return -1;
}
return fr->getLimit(run);
}
U_CAPI const le_font * U_EXPORT2
pl_getFontRunFont(const pl_fontRuns *fontRuns,
le_int32 run)
{
const FontRuns *fr = (const FontRuns *) fontRuns;
if (fr == NULL) {
return NULL;
}
return (const le_font *) fr->getFont(run);
}
U_CAPI le_int32 U_EXPORT2
pl_addFontRun(pl_fontRuns *fontRuns,
const le_font *font,
le_int32 limit)
{
FontRuns *fr = (FontRuns *) fontRuns;
if (fr == NULL) {
return -1;
}
return fr->add((const LEFontInstance *) font, limit);
}
U_CAPI pl_valueRuns * U_EXPORT2
pl_openValueRuns(const le_int32 *values,
const le_int32 *limits,
le_int32 count)
{
return (pl_valueRuns *) new ValueRuns(values, limits, count);
}
U_CAPI pl_valueRuns * U_EXPORT2
pl_openEmptyValueRuns(le_int32 initialCapacity)
{
return (pl_valueRuns *) new ValueRuns(initialCapacity);
}
U_CAPI void U_EXPORT2
pl_closeValueRuns(pl_valueRuns *valueRuns)
{
ValueRuns *vr = (ValueRuns *) valueRuns;
delete vr;
}
U_CAPI le_int32 U_EXPORT2
pl_getValueRunCount(const pl_valueRuns *valueRuns)
{
const ValueRuns *vr = (const ValueRuns *) valueRuns;
if (vr == NULL) {
return -1;
}
return vr->getCount();
}
U_CAPI void U_EXPORT2
pl_resetValueRuns(pl_valueRuns *valueRuns)
{
ValueRuns *vr = (ValueRuns *) valueRuns;
if (vr != NULL) {
vr->reset();
}
}
U_CAPI le_int32 U_EXPORT2
pl_getValueRunLastLimit(const pl_valueRuns *valueRuns)
{
const ValueRuns *vr = (const ValueRuns *) valueRuns;
if (vr == NULL) {
return -1;
}
return vr->getLimit();
}
U_CAPI le_int32 U_EXPORT2
pl_getValueRunLimit(const pl_valueRuns *valueRuns,
le_int32 run)
{
const ValueRuns *vr = (const ValueRuns *) valueRuns;
if (vr == NULL) {
return -1;
}
return vr->getLimit(run);
}
U_CAPI le_int32 U_EXPORT2
pl_getValueRunValue(const pl_valueRuns *valueRuns,
le_int32 run)
{
const ValueRuns *vr = (const ValueRuns *) valueRuns;
if (vr == NULL) {
return -1;
}
return vr->getValue(run);
}
U_CAPI le_int32 U_EXPORT2
pl_addValueRun(pl_valueRuns *valueRuns,
le_int32 value,
le_int32 limit)
{
ValueRuns *vr = (ValueRuns *) valueRuns;
if (vr == NULL) {
return -1;
}
return vr->add(value, limit);
}
class ULocRuns : public LocaleRuns
{
public:
/**
* Construct a <code>LocaleRuns</code> object from pre-existing arrays of locales
* and limit indices.
*
* @param locales is the address of an array of locale name strings. This array,
* and the <code>Locale</code> objects to which it points, must remain valid until
* the <code>LocaleRuns</code> object is destroyed.
*
* @param limits is the address of an array of limit indices. This array must remain valid until the
* <code>LocaleRuns</code> object is destroyed.
*
* @param count is the number of entries in the two arrays.
*
* @draft ICU 3.8
*/
ULocRuns(const char **locales, const le_int32 *limits, le_int32 count);
/**
* Construct an empty <code>LoIDRuns</code> object. Clients can add locale and limit
* indices arrays using the <code>add</code> method.
*
* @param initialCapacity is the initial size of the locale and limit indices arrays. If
* this value is zero, no arrays will be allocated.
*
* @see add
*
* @draft ICU 3.8
*/
ULocRuns(le_int32 initialCapacity);
/**
* The destructor; virtual so that subclass destructors are invoked as well.
*
* @draft ICU 3.8
*/
virtual ~ULocRuns();
/**
* Get the name of the locale assoicated with the given run
* of text. Use <code>RunArray::getLimit(run)</code> to get the corresponding
* limit index.
*
* @param run is the index into the font and limit indices arrays.
*
* @return the locale name associated with the given text run.
*
* @see RunArray::getLimit
*
* @draft ICU 3.8
*/
const char *getLocaleName(le_int32 run) const;
/**
* Add a <code>Locale</code> and limit index pair to the data arrays and return
* the run index where the data was stored. This method calls
* <code>RunArray::add(limit)</code> which will create or grow the arrays as needed.
*
* If the <code>ULocRuns</code> object was created with a client-supplied
* locale and limit indices arrays, this method will return a run index of -1.
*
* Subclasses should not override this method. Rather they should provide a new <code>add</code>
* method which takes a locale name and a limit index along with whatever other data they implement.
* The new <code>add</code> method should first call this method to grow the font and limit indices
* arrays, and use the returned run index to store data their own arrays.
*
* @param locale is the name of the locale to add. This object must remain valid
* until the <code>ULocRuns</code> object is destroyed.
*
* @param limit is the limit index to add
*
* @return the run index where the locale and limit index were stored, or -1 if the data cannot be stored.
*
* @draft ICU 3.8
*/
le_int32 add(const char *locale, le_int32 limit);
/**
* ICU "poor man's RTTI", returns a UClassID for this class.
*
* @draft ICU 3.8
*/
static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
*
* @draft ICU 3.8
*/
virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
protected:
virtual void init(le_int32 capacity);
virtual void grow(le_int32 capacity);
private:
inline ULocRuns();
inline ULocRuns(const ULocRuns &other);
inline ULocRuns &operator=(const ULocRuns & /*other*/) { return *this; };
/**
* The address of this static class variable serves as this class's ID
* for ICU "poor man's RTTI".
*/
static const char fgClassID;
const char **fLocaleNames;
Locale **fLocalesCopy;
};
const char ULocRuns::fgClassID = 0;
inline ULocRuns::ULocRuns()
: LocaleRuns(0), fLocaleNames(NULL)
{
// nothing else to do...
}
inline ULocRuns::ULocRuns(const ULocRuns & /*other*/)
: LocaleRuns(0), fLocaleNames(NULL)
{
// nothing else to do...
}
const Locale **getLocales(const char **localeNames, le_int32 count)
{
Locale **locales = LE_NEW_ARRAY(Locale *, count);
for (int i = 0; i < count; i += 1) {
locales[i] = new Locale(Locale::createFromName(localeNames[i]));
}
return (const Locale **) locales;
}
ULocRuns::ULocRuns(const char **locales, const le_int32 *limits, le_int32 count)
: LocaleRuns(getLocales(locales, count), limits, count), fLocaleNames(locales)
{
// nothing else to do...
}
ULocRuns::ULocRuns(le_int32 initialCapacity)
: LocaleRuns(initialCapacity), fLocaleNames(NULL)
{
if(initialCapacity > 0) {
fLocaleNames = LE_NEW_ARRAY(const char *, initialCapacity);
}
}
ULocRuns::~ULocRuns()
{
le_int32 count = getCount();
for(int i = 0; i < count; i += 1) {
delete fLocales[i];
}
if (fClientArrays) {
LE_DELETE_ARRAY(fLocales);
fLocales = NULL;
} else {
LE_DELETE_ARRAY(fLocaleNames);
fLocaleNames = NULL;
}
}
void ULocRuns::init(le_int32 capacity)
{
LocaleRuns::init(capacity);
fLocaleNames = LE_NEW_ARRAY(const char *, capacity);
}
void ULocRuns::grow(le_int32 capacity)
{
RunArray::grow(capacity);
fLocaleNames = (const char **) LE_GROW_ARRAY(fLocaleNames, capacity);
}
le_int32 ULocRuns::add(const char *locale, le_int32 limit)
{
Locale *loc = new Locale(Locale::createFromName(locale));
le_int32 index = LocaleRuns::add(loc, limit);
if (index >= 0) {
char **localeNames = (char **) fLocaleNames;
localeNames[index] = (char *) locale;
}
return index;
}
const char *ULocRuns::getLocaleName(le_int32 run) const
{
if (run < 0 || run >= getCount()) {
return NULL;
}
return fLocaleNames[run];
}
U_CAPI pl_localeRuns * U_EXPORT2
pl_openLocaleRuns(const char **locales,
const le_int32 *limits,
le_int32 count)
{
return (pl_localeRuns *) new ULocRuns(locales, limits, count);
}
U_CAPI pl_localeRuns * U_EXPORT2
pl_openEmptyLocaleRuns(le_int32 initialCapacity)
{
return (pl_localeRuns *) new ULocRuns(initialCapacity);
}
U_CAPI void U_EXPORT2
pl_closeLocaleRuns(pl_localeRuns *localeRuns)
{
ULocRuns *lr = (ULocRuns *) localeRuns;
delete lr;
}
U_CAPI le_int32 U_EXPORT2
pl_getLocaleRunCount(const pl_localeRuns *localeRuns)
{
const ULocRuns *lr = (const ULocRuns *) localeRuns;
if (lr == NULL) {
return -1;
}
return lr->getCount();
}
U_CAPI void U_EXPORT2
pl_resetLocaleRuns(pl_localeRuns *localeRuns)
{
ULocRuns *lr = (ULocRuns *) localeRuns;
if (lr != NULL) {
lr->reset();
}
}
U_CAPI le_int32 U_EXPORT2
pl_getLocaleRunLastLimit(const pl_localeRuns *localeRuns)
{
const ULocRuns *lr = (const ULocRuns *) localeRuns;
if (lr == NULL) {
return -1;
}
return lr->getLimit();
}
U_CAPI le_int32 U_EXPORT2
pl_getLocaleRunLimit(const pl_localeRuns *localeRuns,
le_int32 run)
{
const ULocRuns *lr = (const ULocRuns *) localeRuns;
if (lr == NULL) {
return -1;
}
return lr->getLimit(run);
}
U_CAPI const char * U_EXPORT2
pl_getLocaleRunLocale(const pl_localeRuns *localeRuns,
le_int32 run)
{
const ULocRuns *lr = (const ULocRuns *) localeRuns;
if (lr == NULL) {
return NULL;
}
return lr->getLocaleName(run);
}
U_CAPI le_int32 U_EXPORT2
pl_addLocaleRun(pl_localeRuns *localeRuns,
const char *locale,
le_int32 limit)
{
ULocRuns *lr = (ULocRuns *) localeRuns;
if (lr == NULL) {
return -1;
}
return lr->add(locale, limit);
}

View File

@ -166,14 +166,12 @@ le_bool GnomeFontInstance::getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber,
return FALSE; return FALSE;
} }
FT_OutlineGlyph oglyph = (FT_OutlineGlyph) fFace->glyph; if (pointNumber >= fFace->glyph->outline.n_points) {
if (pointNumber >= oglyph->outline.n_points) {
return FALSE; return FALSE;
} }
point.fX = oglyph->outline.points[pointNumber].x >> 6; point.fX = fFace->glyph->outline.points[pointNumber].x >> 6;
point.fY = oglyph->outline.points[pointNumber].y >> 6; point.fY = fFace->glyph->outline.points[pointNumber].y >> 6;
return TRUE; return TRUE;
} }

View File

@ -1,5 +1,5 @@
## Makefile.in for ICU - samples/layout ## Makefile.in for ICU - samples/layout
## Copyright (c) 2001-2003, International Business Machines Corporation and ## Copyright (c) 2001-2007, International Business Machines Corporation and
## others. All Rights Reserved. ## others. All Rights Reserved.
## Source directory information ## Source directory information
@ -20,13 +20,18 @@ subdir = samples/layout
CLEANFILES = *~ $(DEPS) CLEANFILES = *~ $(DEPS)
## Target information ## Target information
TARGET = gnomelayout TARGET = gnomelayout
CTARGET = cgnomelayout
CPPFLAGS += -DLE_USE_CMEMORY `pkg-config --cflags libgnomeui-2.0 freetype2 cairo` -I$(top_builddir)/common -I$(top_srcdir)/common -I$(top_srcdir)/i18n -I$(top_srcdir)/layoutex -I$(top_srcdir)/layout -I$(top_srcdir) -g CPPFLAGS += -DLE_USE_CMEMORY `pkg-config --cflags libgnomeui-2.0 freetype2 cairo` -I$(top_builddir)/common -I$(top_srcdir)/common -I$(top_srcdir)/i18n -I$(top_srcdir)/layoutex -I$(top_srcdir)/layout -I$(top_srcdir) -g
LIBS = $(LIBICULX) $(LIBICULE) $(LIBICUUC) $(LIBICUI18N) @LIBS@ @LIB_M@ `pkg-config --libs libgnomeui-2.0 freetype2 cairo` LIBS = $(LIBICULX) $(LIBICULE) $(LIBICUUC) $(LIBICUI18N) @LIBS@ @LIB_M@ `pkg-config --libs libgnomeui-2.0 freetype2 cairo`
OBJECTS=cmaps.o UnicodeReader.o GnomeGUISupport.o FontMap.o GnomeFontMap.o ScriptCompositeFontInstance.o GnomeFontInstance.o FontTableCache.o paragraph.o gnomelayout.o COMMON=cmaps.o UnicodeReader.o GnomeGUISupport.o FontMap.o GnomeFontMap.o ScriptCompositeFontInstance.o GnomeFontInstance.o FontTableCache.o paragraph.o
OBJECTS=gnomelayout.o
COBJECTS=gnomeglue.o pflow.o rsurface.o ucreader.o cgnomelayout.o
DEPS = $(OBJECTS:.o=.d) DEPS = $(OBJECTS:.o=.d)
@ -44,16 +49,20 @@ clean: clean-local
distclean : distclean-local distclean : distclean-local
dist: dist-local dist: dist-local
check: all check-local check: all check-local
c-all: c-all-local
c-check: c-all c-check-local
all-local: $(TARGET) all-local: $(TARGET)
c-all-local: $(CTARGET)
install-local: install-local:
dist-local: dist-local:
clean-local: clean-local:
test -z "$(CLEANFILES)" || $(RMV) $(CLEANFILES) test -z "$(CLEANFILES)" || $(RMV) $(CLEANFILES)
$(RMV) $(OBJECTS) $(TARGET) $(RMV) $(COMMON) $(OBJECTS) $(COBJECTS) $(TARGET)
distclean-local: clean-local distclean-local: clean-local
$(RMV) Makefile $(RMV) Makefile
@ -61,6 +70,9 @@ distclean-local: clean-local
check-local: all-local check-local: all-local
$(INVOKE) ./$(TARGET) $(INVOKE) ./$(TARGET)
c-check-local: c-all-local
$(INVOKE) ./$(CTARGET)
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \ cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
@ -77,7 +89,10 @@ scrptrun.d: $(top_srcdir)/extra/scrptrun/scrptrun.cpp
scrptrun.o: $(top_srcdir)/extra/scrptrun/scrptrun.cpp scrptrun.o: $(top_srcdir)/extra/scrptrun/scrptrun.cpp
$(COMPILE.cc) $(DYNAMICCPPFLAGS) $(DYNAMICCXXFLAGS) -o $@ $< $(COMPILE.cc) $(DYNAMICCPPFLAGS) $(DYNAMICCXXFLAGS) -o $@ $<
$(TARGET) : $(OBJECTS) $(TARGET) : $(COMMON) $(OBJECTS)
$(LINK.cc) -o $@ $^ $(LIBS)
$(CTARGET) : $(COMMON) $(COBJECTS)
$(LINK.cc) -o $@ $^ $(LIBS) $(LINK.cc) -o $@ $^ $(LIBS)
invoke: invoke:

View File

@ -0,0 +1,22 @@
/*
*
* (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
*
*/
#ifndef __ARRAYMEM_H
#define __ARRAYMEM_H
#include <stdlib.h>
#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
#define ARRAY_COPY(dst, src, count) memcpy((void *) (dst), (void *) (src), (count) * sizeof (src)[0])
#define NEW_ARRAY(type,count) (type *) malloc((count) * sizeof(type))
#define DELETE_ARRAY(array) free((void *) (array))
#define GROW_ARRAY(array,newSize) realloc((void *) (array), (newSize) * sizeof (array)[0])
#endif

View File

@ -0,0 +1,342 @@
/*
****************************************************************************** *
*
* Copyright (C) 1999-2007, International Business Machines
* Corporation and others. All Rights Reserved.
*
****************************************************************************** *
*/
#include <gnome.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include "pflow.h"
#include "gnomeglue.h"
#include "arraymem.h"
struct Context
{
long width;
long height;
pf_flow *paragraph;
};
typedef struct Context Context;
static FT_Library engine;
static gs_guiSupport *guiSupport;
static fm_fontMap *fontMap;
static le_font *font;
static GSList *appList = NULL;
GtkWidget *newSample(const gchar *fileName);
void closeSample(GtkWidget *sample);
static void showabout(GtkWidget *widget, gpointer data)
{
GtkWidget *aboutBox;
const gchar *documentedBy[] = {NULL};
const gchar *writtenBy[] = {
"Eric Mader",
NULL
};
aboutBox = gnome_about_new("Gnome Layout Sample",
"0.1",
"Copyright (C) 1998-2006 By International Business Machines Corporation and others. All Rights Reserved.",
"A simple demo of the ICU LayoutEngine.",
writtenBy,
documentedBy,
"",
NULL);
gtk_widget_show(aboutBox);
}
#if 0
static void notimpl(GtkObject *object, gpointer data)
{
gnome_ok_dialog("Not implemented...");
}
#endif
static gchar *prettyTitle(const gchar *path)
{
const gchar *name = g_basename(path);
gchar *title = g_strconcat("Gnome Layout Sample - ", name, NULL);
return title;
}
static void openOK(GtkObject *object, gpointer data)
{
GtkFileSelection *fileselection = GTK_FILE_SELECTION(data);
GtkWidget *app = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(fileselection), "app"));
Context *context = (Context *) gtk_object_get_data(GTK_OBJECT(app), "context");
gchar *fileName = g_strdup(gtk_file_selection_get_filename(fileselection));
pf_flow *newPara;
gtk_widget_destroy(GTK_WIDGET(fileselection));
newPara = pf_factory(fileName, font, guiSupport);
if (newPara != NULL) {
gchar *title = prettyTitle(fileName);
GtkWidget *area = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(app), "area"));
if (context->paragraph != NULL) {
pf_close(context->paragraph);
}
context->paragraph = newPara;
gtk_window_set_title(GTK_WINDOW(app), title);
gtk_widget_hide(area);
pf_breakLines(context->paragraph, context->width, context->height);
gtk_widget_show_all(area);
g_free(title);
}
g_free(fileName);
}
static void openfile(GtkObject *object, gpointer data)
{
GtkWidget *app = GTK_WIDGET(data);
GtkWidget *fileselection;
GtkWidget *okButton;
GtkWidget *cancelButton;
fileselection =
gtk_file_selection_new("Open File");
gtk_object_set_data(GTK_OBJECT(fileselection), "app", app);
okButton =
GTK_FILE_SELECTION(fileselection)->ok_button;
cancelButton =
GTK_FILE_SELECTION(fileselection)->cancel_button;
gtk_signal_connect(GTK_OBJECT(fileselection), "destroy",
GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
gtk_signal_connect(GTK_OBJECT(okButton), "clicked",
GTK_SIGNAL_FUNC(openOK), fileselection);
gtk_signal_connect_object(GTK_OBJECT(cancelButton), "clicked",
GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(fileselection));
gtk_window_set_modal(GTK_WINDOW(fileselection), TRUE);
gtk_widget_show(fileselection);
gtk_main();
}
static void newapp(GtkObject *object, gpointer data)
{
GtkWidget *app = newSample("Sample.txt");
gtk_widget_show_all(app);
}
static void closeapp(GtkWidget *widget, gpointer data)
{
GtkWidget *app = GTK_WIDGET(data);
closeSample(app);
}
static void shutdown(GtkObject *object, gpointer data)
{
gtk_main_quit();
}
GnomeUIInfo fileMenu[] =
{
GNOMEUIINFO_MENU_NEW_ITEM((gchar *) "_New Sample",
(gchar *) "Create a new Gnome Layout Sample",
newapp, NULL),
GNOMEUIINFO_MENU_OPEN_ITEM(openfile, NULL),
GNOMEUIINFO_SEPARATOR,
GNOMEUIINFO_MENU_CLOSE_ITEM(closeapp, NULL),
GNOMEUIINFO_MENU_EXIT_ITEM(shutdown, NULL),
GNOMEUIINFO_END
};
GnomeUIInfo helpMenu[] =
{
/* GNOMEUIINFO_HELP("gnomelayout"), */
GNOMEUIINFO_MENU_ABOUT_ITEM(showabout, NULL),
GNOMEUIINFO_END
};
GnomeUIInfo mainMenu[] =
{
GNOMEUIINFO_SUBTREE(N_((gchar *) "File"), fileMenu),
GNOMEUIINFO_SUBTREE(N_((gchar *) "Help"), helpMenu),
GNOMEUIINFO_END
};
static gint eventDelete(GtkWidget *widget, GdkEvent *event, gpointer data)
{
closeSample(widget);
/* indicate that closeapp already destroyed the window */
return TRUE;
}
static gint eventConfigure(GtkWidget *widget, GdkEventConfigure *event, Context *context)
{
if (context->paragraph != NULL) {
context->width = event->width;
context->height = event->height;
if (context->width > 0 && context->height > 0) {
pf_breakLines(context->paragraph, context->width, context->height);
}
}
return TRUE;
}
static gint eventExpose(GtkWidget *widget, GdkEvent *event, Context *context)
{
if (context->paragraph != NULL) {
gint maxLines = pf_getLineCount(context->paragraph) - 1;
gint firstLine = 0, lastLine = context->height / pf_getLineHeight(context->paragraph);
rs_surface *surface = rs_gnomeRenderingSurfaceOpen(widget);
pf_draw(context->paragraph, surface, firstLine, (maxLines < lastLine)? maxLines : lastLine);
rs_gnomeRenderingSurfaceClose(surface);
}
return TRUE;
}
GtkWidget *newSample(const gchar *fileName)
{
Context *context = NEW_ARRAY(Context, 1);
gchar *title;
GtkWidget *app;
GtkWidget *area;
GtkStyle *style;
int i;
context->width = 600;
context->height = 400;
context->paragraph = pf_factory(fileName, font, guiSupport);
title = prettyTitle(fileName);
app = gnome_app_new("gnomeLayout", title);
gtk_object_set_data(GTK_OBJECT(app), "context", context);
gtk_window_set_default_size(GTK_WINDOW(app), 600 - 24, 400);
gnome_app_create_menus_with_data(GNOME_APP(app), mainMenu, app);
gtk_signal_connect(GTK_OBJECT(app), "delete_event",
GTK_SIGNAL_FUNC(eventDelete), NULL);
area = gtk_drawing_area_new();
gtk_object_set_data(GTK_OBJECT(app), "area", area);
style = gtk_style_copy(gtk_widget_get_style(area));
for (i = 0; i < 5; i += 1) {
style->fg[i] = style->white;
}
gtk_widget_set_style(area, style);
gnome_app_set_contents(GNOME_APP(app), area);
gtk_signal_connect(GTK_OBJECT(area),
"expose_event",
GTK_SIGNAL_FUNC(eventExpose),
context);
gtk_signal_connect(GTK_OBJECT(area),
"configure_event",
GTK_SIGNAL_FUNC(eventConfigure),
context);
appList = g_slist_prepend(appList, app);
g_free(title);
return app;
}
void closeSample(GtkWidget *app)
{
Context *context = (Context *) gtk_object_get_data(GTK_OBJECT(app), "context");
if (context->paragraph != NULL) {
pf_close(context->paragraph);
}
DELETE_ARRAY(context);
appList = g_slist_remove(appList, app);
gtk_widget_destroy(app);
if (appList == NULL) {
gtk_main_quit();
}
}
int main (int argc, char *argv[])
{
LEErrorCode fontStatus = LE_NO_ERROR;
poptContext ptctx;
GtkWidget *app;
const char *defaultArgs[] = {"Sample.txt", NULL};
const char **args;
int i;
FT_Init_FreeType(&engine);
gnome_init_with_popt_table("gnomelayout", "0.1", argc, argv, NULL, 0, &ptctx);
guiSupport = gs_gnomeGuiSupportOpen();
fontMap = fm_gnomeFontMapOpen(engine, "FontMap.Gnome", 24, guiSupport, &fontStatus);
font = le_scriptCompositeFontOpen(fontMap);
if (LE_FAILURE(fontStatus)) {
FT_Done_FreeType(engine);
return 1;
}
args = poptGetArgs(ptctx);
if (args == NULL) {
args = defaultArgs;
}
for (i = 0; args[i] != NULL; i += 1) {
app = newSample(args[i]);
gtk_widget_show_all(app);
}
poptFreeContext(ptctx);
gtk_main();
le_fontClose(font);
gs_gnomeGuiSupportClose(guiSupport);
FT_Done_FreeType(engine);
exit(0);
}

View File

@ -0,0 +1,363 @@
/*
*******************************************************************************
*
* Copyright (C) 1999-2007, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
* file name: Layout.cpp
*
* created on: 08/03/2000
* created by: Eric R. Mader
*/
#include <windows.h>
#include <stdio.h>
#include "playout.h"
#include "pflow.h"
#include "gdiglue.h"
#include "ucreader.h"
#include "arraymem.h"
#include "resource.h"
struct Context
{
le_int32 width;
le_int32 height;
pf_flow *paragraph;
};
typedef struct Context Context;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
#define APP_NAME "LayoutSample"
TCHAR szAppName[] = TEXT(APP_NAME);
void PrettyTitle(HWND hwnd, char *fileName)
{
char title[MAX_PATH + 64];
sprintf(title, "%s - %s", APP_NAME, fileName);
SetWindowTextA(hwnd, title);
}
void InitParagraph(HWND hwnd, Context *context)
{
SCROLLINFO si;
if (context->paragraph != NULL) {
// FIXME: does it matter what we put in the ScrollInfo
// if the window's been minimized?
if (context->width > 0 && context->height > 0) {
pf_breakLines(context->paragraph, context->width, context->height);
}
si.cbSize = sizeof si;
si.fMask = SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL;
si.nMin = 0;
si.nMax = pf_getLineCount(context->paragraph) - 1;
si.nPage = context->height / pf_getLineHeight(context->paragraph);
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
HWND hwnd;
HACCEL hAccel;
MSG msg;
WNDCLASS wndclass;
LEErrorCode status = LE_NO_ERROR;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = sizeof(LONG);
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = szAppName;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass)) {
MessageBox(NULL, TEXT("This demo only runs on Windows 2000!"), szAppName, MB_ICONERROR);
return 0;
}
hAccel = LoadAccelerators(hInstance, szAppName);
hwnd = CreateWindow(szAppName, NULL,
WS_OVERLAPPEDWINDOW | WS_VSCROLL,
CW_USEDEFAULT, CW_USEDEFAULT,
600, 400,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0)) {
if (!TranslateAccelerator(hwnd, hAccel, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
UnregisterClass(szAppName, hInstance);
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
Context *context;
static le_int32 windowCount = 0;
static fm_fontMap *fontMap = NULL;
static rs_surface *surface = NULL;
static gs_guiSupport *guiSupport = NULL;
static le_font *font = NULL;
switch (message) {
case WM_CREATE:
{
LEErrorCode fontStatus = LE_NO_ERROR;
hdc = GetDC(hwnd);
guiSupport = gs_gdiGuiSupportOpen();
surface = rs_gdiRenderingSurfaceOpen(hdc);
fontMap = fm_gdiFontMapOpen(surface, "FontMap.GDI", 24, guiSupport, &fontStatus);
font = le_scriptCompositeFontOpen(fontMap);
if (LE_FAILURE(fontStatus)) {
ReleaseDC(hwnd, hdc);
return -1;
}
context = NEW_ARRAY(Context, 1);
context->width = 600;
context->height = 400;
context->paragraph = pf_factory("Sample.txt", font, guiSupport);
SetWindowLongPtr(hwnd, 0, (LONG_PTR) context);
windowCount += 1;
ReleaseDC(hwnd, hdc);
PrettyTitle(hwnd, "Sample.txt");
return 0;
}
case WM_SIZE:
{
context = (Context *) GetWindowLongPtr(hwnd, 0);
context->width = LOWORD(lParam);
context->height = HIWORD(lParam);
InitParagraph(hwnd, context);
return 0;
}
case WM_VSCROLL:
{
SCROLLINFO si;
le_int32 vertPos;
si.cbSize = sizeof si;
si.fMask = SIF_ALL;
GetScrollInfo(hwnd, SB_VERT, &si);
vertPos = si.nPos;
switch (LOWORD(wParam))
{
case SB_TOP:
si.nPos = si.nMin;
break;
case SB_BOTTOM:
si.nPos = si.nMax;
break;
case SB_LINEUP:
si.nPos -= 1;
break;
case SB_LINEDOWN:
si.nPos += 1;
break;
case SB_PAGEUP:
si.nPos -= si.nPage;
break;
case SB_PAGEDOWN:
si.nPos += si.nPage;
break;
case SB_THUMBTRACK:
si.nPos = si.nTrackPos;
break;
default:
break;
}
si.fMask = SIF_POS;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
GetScrollInfo(hwnd, SB_VERT, &si);
context = (Context *) GetWindowLongPtr(hwnd, 0);
if (context->paragraph != NULL && si.nPos != vertPos) {
ScrollWindow(hwnd, 0, pf_getLineHeight(context->paragraph) * (vertPos - si.nPos), NULL, NULL);
UpdateWindow(hwnd);
}
return 0;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
SCROLLINFO si;
le_int32 firstLine, lastLine;
hdc = BeginPaint(hwnd, &ps);
SetBkMode(hdc, TRANSPARENT);
si.cbSize = sizeof si;
si.fMask = SIF_ALL;
GetScrollInfo(hwnd, SB_VERT, &si);
firstLine = si.nPos;
context = (Context *) GetWindowLongPtr(hwnd, 0);
if (context->paragraph != NULL) {
rs_gdiRenderingSurfaceSetHDC(surface, hdc);
// NOTE: si.nPos + si.nPage may include a partial line at the bottom
// of the window. We need this because scrolling assumes that the
// partial line has been painted.
lastLine = min (si.nPos + (le_int32) si.nPage, pf_getLineCount(context->paragraph) - 1);
pf_draw(context->paragraph, surface, firstLine, lastLine);
}
EndPaint(hwnd, &ps);
return 0;
}
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDM_FILE_OPEN:
{
OPENFILENAMEA ofn;
char szFileName[MAX_PATH], szTitleName[MAX_PATH];
static char szFilter[] = "Text Files (.txt)\0*.txt\0"
"All Files (*.*)\0*.*\0\0";
ofn.lStructSize = sizeof (OPENFILENAMEA);
ofn.hwndOwner = hwnd;
ofn.hInstance = NULL;
ofn.lpstrFilter = szFilter;
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 0;
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFileTitle = szTitleName;
ofn.nMaxFileTitle = MAX_PATH;
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = NULL;
ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
ofn.nFileOffset = 0;
ofn.nFileExtension = 0;
ofn.lpstrDefExt = "txt";
ofn.lCustData = 0L;
ofn.lpfnHook = NULL;
ofn.lpTemplateName = NULL;
szFileName[0] = '\0';
if (GetOpenFileNameA(&ofn)) {
pf_flow *newParagraph;
hdc = GetDC(hwnd);
rs_gdiRenderingSurfaceSetHDC(surface, hdc);
newParagraph = pf_factory(szFileName, font, guiSupport);
if (newParagraph != NULL) {
context = (Context *) GetWindowLongPtr(hwnd, 0);
if (context->paragraph != NULL) {
pf_close(context->paragraph);
}
context->paragraph = newParagraph;
InitParagraph(hwnd, context);
PrettyTitle(hwnd, szTitleName);
InvalidateRect(hwnd, NULL, TRUE);
}
}
//ReleaseDC(hwnd, hdc);
return 0;
}
case IDM_FILE_EXIT:
case IDM_FILE_CLOSE:
SendMessage(hwnd, WM_CLOSE, 0, 0);
return 0;
case IDM_HELP_ABOUTLAYOUTSAMPLE:
MessageBox(hwnd, TEXT("Windows Layout Sample 0.1\n")
TEXT("Copyright (C) 1998-2005 By International Business Machines Corporation and others.\n")
TEXT("Author: Eric Mader"),
szAppName, MB_ICONINFORMATION | MB_OK);
return 0;
}
break;
case WM_DESTROY:
{
context = (Context *) GetWindowLongPtr(hwnd, 0);
if (context != NULL && context->paragraph != NULL) {
pf_close(context->paragraph);
}
DELETE_ARRAY(context);
if (--windowCount <= 0) {
le_fontClose(font);
rs_gdiRenderingSurfaceClose(surface);
gs_gdiGuiSupportClose(guiSupport);
PostQuitMessage(0);
}
return 0;
}
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}

View File

@ -0,0 +1,80 @@
/*
*
* (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
*
*/
#include <windows.h>
#include "unicode/utypes.h"
#include "loengine.h"
#include "rsurface.h"
#include "gsupport.h"
#include "gdiglue.h"
#include "LETypes.h"
#include "LEFontInstance.h"
#include "GDIGUISupport.h"
#include "GDIFontMap.h"
#include "ScriptCompositeFontInstance.h"
U_CDECL_BEGIN
gs_guiSupport *gs_gdiGuiSupportOpen()
{
return (gs_guiSupport *) new GDIGUISupport();
}
void gs_gdiGuiSupportClose(gs_guiSupport *guiSupport)
{
GDIGUISupport *gs = (GDIGUISupport *) guiSupport;
delete gs;
}
rs_surface *rs_gdiRenderingSurfaceOpen(HDC hdc)
{
return (rs_surface *) new GDISurface(hdc);
}
void rs_gdiRenderingSurfaceSetHDC(rs_surface *surface, HDC hdc)
{
GDISurface *rs = (GDISurface *) surface;
rs->setHDC(hdc);
}
void rs_gdiRenderingSurfaceClose(rs_surface *surface)
{
GDISurface *rs = (GDISurface *) surface;
delete rs;
}
fm_fontMap *fm_gdiFontMapOpen(rs_surface *surface, const char *fileName, le_int16 pointSize, gs_guiSupport *guiSupport, LEErrorCode *status)
{
return (fm_fontMap *) new GDIFontMap((GDISurface *) surface, fileName, pointSize, (GDIGUISupport *) guiSupport, *status);
}
void fm_fontMapClose(fm_fontMap *fontMap)
{
GDIFontMap *fm = (GDIFontMap *) fontMap;
delete fm;
}
le_font *le_scriptCompositeFontOpen(fm_fontMap *fontMap)
{
return (le_font *) new ScriptCompositeFontInstance((FontMap *) fontMap);
}
void le_fontClose(le_font *font)
{
LEFontInstance *fi = (LEFontInstance *) font;
delete fi;
}
U_CDECL_END

View File

@ -0,0 +1,38 @@
/*
*
* (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
*
*/
#ifndef __GDIGLUE_H
#define __GDIGLUE_H
#include <windows.h>
#include "unicode/utypes.h"
#include "LETypes.h"
#include "loengine.h"
#include "gsupport.h"
#include "rsurface.h"
typedef void fm_fontMap;
U_CDECL_BEGIN
gs_guiSupport *gs_gdiGuiSupportOpen();
void gs_gdiGuiSupportClose(gs_guiSupport *guiSupport);
rs_surface *rs_gdiRenderingSurfaceOpen(HDC hdc);
void rs_gdiRenderingSurfaceSetHDC(rs_surface *surface, HDC hdc);
void rs_gdiRenderingSurfaceClose(rs_surface *surface);
fm_fontMap *fm_gdiFontMapOpen(rs_surface *surface, const char *fileName, le_int16 pointSize, gs_guiSupport *guiSupport, LEErrorCode *status);
void fm_fontMapClose(fm_fontMap *fontMap);
le_font *le_scriptCompositeFontOpen(fm_fontMap *fontMap);
void le_fontClose(le_font *font);
U_CDECL_END
#endif

View File

@ -0,0 +1,76 @@
/*
*
* (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
*
*/
#include <gnome.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include "unicode/utypes.h"
#include "loengine.h"
#include "rsurface.h"
#include "gsupport.h"
#include "gnomeglue.h"
#include "LETypes.h"
#include "LEFontInstance.h"
#include "GnomeGUISupport.h"
#include "GnomeFontMap.h"
#include "GnomeFontInstance.h"
#include "ScriptCompositeFontInstance.h"
U_CDECL_BEGIN
gs_guiSupport *gs_gnomeGuiSupportOpen()
{
return (gs_guiSupport *) new GnomeGUISupport();
}
void gs_gnomeGuiSupportClose(gs_guiSupport *guiSupport)
{
GnomeGUISupport *gs = (GnomeGUISupport *) guiSupport;
delete gs;
}
rs_surface *rs_gnomeRenderingSurfaceOpen(GtkWidget *theWidget)
{
return (rs_surface *) new GnomeSurface(theWidget);
}
void rs_gnomeRenderingSurfaceClose(rs_surface *surface)
{
GnomeSurface *rs = (GnomeSurface *) surface;
delete rs;
}
fm_fontMap *fm_gnomeFontMapOpen(FT_Library engine, const char *fileName, le_int16 pointSize, gs_guiSupport *guiSupport, LEErrorCode *status)
{
return (fm_fontMap *) new GnomeFontMap(engine, fileName, pointSize, (GnomeGUISupport *) guiSupport, *status);
}
void fm_fontMapClose(fm_fontMap *fontMap)
{
GnomeFontMap *fm = (GnomeFontMap *) fontMap;
delete fm;
}
le_font *le_scriptCompositeFontOpen(fm_fontMap *fontMap)
{
return (le_font *) new ScriptCompositeFontInstance((FontMap *) fontMap);
}
void le_fontClose(le_font *font)
{
LEFontInstance *fi = (LEFontInstance *) font;
delete fi;
}
U_CDECL_END

View File

@ -0,0 +1,39 @@
/*
*
* (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
*
*/
#ifndef __GNOMEGLUE_H
#define __GNOMEGLUE_H
#include <gnome.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include "unicode/utypes.h"
#include "LETypes.h"
#include "loengine.h"
#include "gsupport.h"
#include "rsurface.h"
typedef void fm_fontMap;
U_CDECL_BEGIN
gs_guiSupport *gs_gnomeGuiSupportOpen();
void gs_gnomeGuiSupportClose(gs_guiSupport *guiSupport);
rs_surface *rs_gnomeRenderingSurfaceOpen(GtkWidget *theWidget);
void rs_gnomeRenderingSurfaceClose(rs_surface *surface);
fm_fontMap *fm_gnomeFontMapOpen(FT_Library engine, const char *fileName, le_int16 pointSize, gs_guiSupport *guiSupport, LEErrorCode *status);
void fm_fontMapClose(fm_fontMap *fontMap);
le_font *le_scriptCompositeFontOpen(fm_fontMap *fontMap);
void le_fontClose(le_font *font);
U_CDECL_END
#endif

View File

@ -0,0 +1,14 @@
/*
*
* (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
*
*/
#ifndef __GSUPPORT_H
#define __GSUPPORT_H
typedef void gs_guiSupport;
void gs_postErrorMessage(gs_guiSupport *guiSupport, const char *message, const char *title);
#endif

View File

@ -146,7 +146,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
context->height = 400; context->height = 400;
context->paragraph = Paragraph::paragraphFactory("Sample.txt", font, guiSupport); context->paragraph = Paragraph::paragraphFactory("Sample.txt", font, guiSupport);
SetWindowLong(hwnd, 0, (LONG) context); SetWindowLongPtr(hwnd, 0, (LONG_PTR) context);
windowCount += 1; windowCount += 1;
ReleaseDC(hwnd, hdc); ReleaseDC(hwnd, hdc);
@ -157,7 +157,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_SIZE: case WM_SIZE:
{ {
context = (Context *) GetWindowLong(hwnd, 0); context = (Context *) GetWindowLongPtr(hwnd, 0);
context->width = LOWORD(lParam); context->width = LOWORD(lParam);
context->height = HIWORD(lParam); context->height = HIWORD(lParam);
@ -214,7 +214,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
SetScrollInfo(hwnd, SB_VERT, &si, TRUE); SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
GetScrollInfo(hwnd, SB_VERT, &si); GetScrollInfo(hwnd, SB_VERT, &si);
context = (Context *) GetWindowLong(hwnd, 0); context = (Context *) GetWindowLongPtr(hwnd, 0);
if (context->paragraph != NULL && si.nPos != vertPos) { if (context->paragraph != NULL && si.nPos != vertPos) {
ScrollWindow(hwnd, 0, context->paragraph->getLineHeight() * (vertPos - si.nPos), NULL, NULL); ScrollWindow(hwnd, 0, context->paragraph->getLineHeight() * (vertPos - si.nPos), NULL, NULL);
@ -239,7 +239,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
firstLine = si.nPos; firstLine = si.nPos;
context = (Context *) GetWindowLong(hwnd, 0); context = (Context *) GetWindowLongPtr(hwnd, 0);
if (context->paragraph != NULL) { if (context->paragraph != NULL) {
surface->setHDC(hdc); surface->setHDC(hdc);
@ -295,7 +295,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
Paragraph *newParagraph = Paragraph::paragraphFactory(szFileName, font, guiSupport); Paragraph *newParagraph = Paragraph::paragraphFactory(szFileName, font, guiSupport);
if (newParagraph != NULL) { if (newParagraph != NULL) {
context = (Context *) GetWindowLong(hwnd, 0); context = (Context *) GetWindowLongPtr(hwnd, 0);
if (context->paragraph != NULL) { if (context->paragraph != NULL) {
delete context->paragraph; delete context->paragraph;
@ -332,7 +332,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_DESTROY: case WM_DESTROY:
{ {
context = (Context *) GetWindowLong(hwnd, 0); context = (Context *) GetWindowLongPtr(hwnd, 0);
if (context != NULL && context->paragraph != NULL) { if (context != NULL && context->paragraph != NULL) {
delete context->paragraph; delete context->paragraph;

View File

@ -3,7 +3,7 @@
ProjectType="Visual C++" ProjectType="Visual C++"
Version="8.00" Version="8.00"
Name="layout" Name="layout"
ProjectGUID="{EE80B3B5-40F2-46F2-AC4B-FB929683515C}" ProjectGUID="{497500ED-DE1D-4B20-B529-F41B5A0FBEEB}"
> >
<Platforms> <Platforms>
<Platform <Platform

View File

@ -1,7 +1,7 @@
/* /*
******************************************************************************* *******************************************************************************
* *
* Copyright (C) 1999-2005, International Business Machines * Copyright (C) 1999-2007, International Business Machines
* Corporation and others. All Rights Reserved. * Corporation and others. All Rights Reserved.
* *
******************************************************************************* *******************************************************************************
@ -19,11 +19,9 @@
#include "layout/ParagraphLayout.h" #include "layout/ParagraphLayout.h"
#include "RenderingSurface.h" #include "RenderingSurface.h"
#include "ScriptCompositeFontInstance.h"
#include "paragraph.h" #include "paragraph.h"
#include "UnicodeReader.h" #include "UnicodeReader.h"
#include "FontMap.h"
#define MARGIN 10 #define MARGIN 10
#define LINE_GROW 32 #define LINE_GROW 32

View File

@ -1,7 +1,7 @@
/* /*
******************************************************************************* *******************************************************************************
* *
* Copyright (C) 1999-2005, International Business Machines * Copyright (C) 1999-2007, International Business Machines
* Corporation and others. All Rights Reserved. * Corporation and others. All Rights Reserved.
* *
******************************************************************************* *******************************************************************************
@ -21,7 +21,6 @@
#include "GUISupport.h" #include "GUISupport.h"
#include "RenderingSurface.h" #include "RenderingSurface.h"
//#include "FontMap.h"
U_NAMESPACE_USE U_NAMESPACE_USE

View File

@ -0,0 +1,381 @@
/*
*
* (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
*
*/
#include "unicode/utypes.h"
#include "unicode/uchar.h"
#include "unicode/ubidi.h"
#include "unicode/ustring.h"
#include "layout/LETypes.h"
#include "layout/loengine.h"
#include "layout/playout.h"
#include "layout/plruns.h"
#include "pflow.h"
#include "arraymem.h"
#include "ucreader.h"
/*
* Move the line below out of this comment
* to add a locale run to the pl_paragraphs
* that are created.
#define TEST_LOCALE "zh_TW"
*/
#define MARGIN 10
#define LINE_GROW 32
#define PARA_GROW 8
#define CH_LF 0x000A
#define CH_CR 0x000D
#define CH_LSEP 0x2028
#define CH_PSEP 0x2029
struct pf_object
{
pl_paragraph **fParagraphLayout;
le_int32 fParagraphCount;
le_int32 fParagraphMax;
le_int32 fParagraphGrow;
le_int32 fLineCount;
le_int32 fLinesMax;
le_int32 fLinesGrow;
pl_line **fLines;
LEUnicode *fChars;
le_int32 fLineHeight;
le_int32 fAscent;
le_int32 fWidth;
le_int32 fHeight;
UBiDiLevel fParagraphLevel;
};
typedef struct pf_object pf_object;
static LEUnicode *skipLineEnd(LEUnicode *ptr)
{
if (ptr[0] == CH_CR && ptr[1] == CH_LF) {
ptr += 1;
}
return ptr + 1;
}
static le_int32 findFontRun(const pl_fontRuns *fontRuns, le_int32 offset)
{
le_int32 runCount = pl_getFontRunCount(fontRuns);
le_int32 run;
for (run = 0; run < runCount; run += 1) {
if (pl_getFontRunLimit(fontRuns, run) > offset) {
return run;
}
}
return -1;
}
static void subsetFontRuns(const pl_fontRuns *fontRuns, le_int32 start, le_int32 limit, pl_fontRuns *sub)
{
le_int32 startRun = findFontRun(fontRuns, start);
le_int32 endRun = findFontRun(fontRuns, limit - 1);
le_int32 run;
pl_resetFontRuns(sub);
for (run = startRun; run <= endRun; run += 1) {
const le_font *runFont = pl_getFontRunFont(fontRuns, run);
le_int32 runLimit = pl_getFontRunLimit(fontRuns, run) - start;
if (run == endRun) {
runLimit = limit - start;
}
pl_addFontRun(sub, runFont, runLimit);
}
}
pf_flow *pf_create(const LEUnicode chars[], le_int32 charCount, const pl_fontRuns *fontRuns, LEErrorCode *status)
{
pf_object *flow;
le_int32 ascent = 0;
le_int32 descent = 0;
le_int32 leading = 0;
pl_localeRuns *locales = NULL;
pl_fontRuns *fr;
LEUnicode *pStart;
static const LEUnicode separators[] = {CH_LF, CH_CR, CH_LSEP, CH_PSEP, 0x0000};
if (LE_FAILURE(*status)) {
return NULL;
}
flow = NEW_ARRAY(pf_object, 1);
flow->fParagraphLayout = NULL;
flow->fParagraphCount = 0;
flow->fParagraphMax = PARA_GROW;
flow->fParagraphGrow = PARA_GROW;
flow->fLineCount = 0;
flow->fLinesMax = LINE_GROW;
flow->fLinesGrow = LINE_GROW;
flow->fLines = NULL;
flow->fChars = NULL;
flow->fLineHeight = -1;
flow->fAscent = -1;
flow->fWidth = -1;
flow->fHeight = -1;
flow->fParagraphLevel = UBIDI_DEFAULT_LTR;
fr = pl_openEmptyFontRuns(0);
#ifdef TEST_LOCALE
locales = pl_openEmptyLocaleRuns(0);
#endif
flow->fLines = NEW_ARRAY(pl_line *, flow->fLinesMax);
flow->fParagraphLayout = NEW_ARRAY(pl_paragraph *, flow->fParagraphMax);
flow->fChars = NEW_ARRAY(LEUnicode, charCount + 1);
LE_ARRAY_COPY(flow->fChars, chars, charCount);
flow->fChars[charCount] = 0;
pStart = &flow->fChars[0];
while (*pStart != 0) {
LEUnicode *pEnd = u_strpbrk(pStart, separators);
le_int32 pAscent, pDescent, pLeading;
pl_paragraph *paragraphLayout = NULL;
if (pEnd == NULL) {
pEnd = &flow->fChars[charCount];
}
if (pEnd != pStart) {
subsetFontRuns(fontRuns, pStart - flow->fChars, pEnd - flow->fChars, fr);
#ifdef TEST_LOCALE
pl_resetLocaleRuns(locales);
pl_addLocaleRun(locales, TEST_LOCALE, pEnd - pStart);
#endif
paragraphLayout = pl_create(pStart, pEnd - pStart, fr, NULL, NULL, locales, flow->fParagraphLevel, FALSE, status);
if (LE_FAILURE(*status)) {
break; /* return? something else? */
}
if (flow->fParagraphLevel == UBIDI_DEFAULT_LTR) {
flow->fParagraphLevel = pl_getParagraphLevel(paragraphLayout);
}
pAscent = pl_getAscent(paragraphLayout);
pDescent = pl_getDescent(paragraphLayout);
pLeading = pl_getLeading(paragraphLayout);
if (pAscent > ascent) {
ascent = pAscent;
}
if (pDescent > descent) {
descent = pDescent;
}
if (pLeading > leading) {
leading = pLeading;
}
}
if (flow->fParagraphCount >= flow->fParagraphMax) {
flow->fParagraphLayout = (pl_paragraph **) GROW_ARRAY(flow->fParagraphLayout, flow->fParagraphMax + flow->fParagraphGrow);
flow->fParagraphMax += flow->fParagraphGrow;
}
flow->fParagraphLayout[flow->fParagraphCount++] = paragraphLayout;
if (*pEnd == 0) {
break;
}
pStart = skipLineEnd(pEnd);
}
flow->fLineHeight = ascent + descent + leading;
flow->fAscent = ascent;
pl_closeLocaleRuns(locales);
pl_closeFontRuns(fr);
return (pf_flow *) flow;
}
void pf_close(pf_flow *flow)
{
pf_object *obj = (pf_object *) flow;
le_int32 i;
for (i = 0; i < obj->fLineCount; i += 1) {
DELETE_ARRAY(obj->fLines[i]);
}
DELETE_ARRAY(obj->fLines);
for (i = 0; i < obj->fParagraphCount; i += 1) {
pl_close(obj->fParagraphLayout[i]);
}
DELETE_ARRAY(obj->fParagraphLayout);
DELETE_ARRAY(obj->fChars);
DELETE_ARRAY(obj);
}
le_int32 pf_getAscent(pf_flow *flow)
{
pf_object *obj = (pf_object *) flow;
return obj->fAscent;
}
le_int32 pf_getLineHeight(pf_flow *flow)
{
pf_object *obj = (pf_object *) flow;
return obj->fLineHeight;
}
le_int32 pf_getLineCount(pf_flow *flow)
{
pf_object *obj = (pf_object *) flow;
return obj->fLineCount;
}
static void addLine(pf_object *obj, pl_line *line)
{
if (obj->fLineCount >= obj->fLinesMax) {
obj->fLines = (pl_line **) GROW_ARRAY(obj->fLines, obj->fLinesMax + obj->fLinesGrow);
obj->fLinesMax += obj->fLinesGrow;
}
obj->fLines[obj->fLineCount++] = line;
}
void pf_breakLines(pf_flow *flow, le_int32 width, le_int32 height)
{
pf_object *obj = (pf_object *) flow;
le_int32 li, p;
float lineWidth;
pl_line *line;
obj->fHeight = height;
/* don't re-break if the width hasn't changed */
if (obj->fWidth == width) {
return;
}
obj->fWidth = width;
lineWidth = (float) (width - 2 * MARGIN);
/* Free the old Lines... */
for (li = 0; li < obj->fLineCount; li += 1) {
pl_closeLine(obj->fLines[li]);
}
obj->fLineCount = 0;
for (p = 0; p < obj->fParagraphCount; p += 1) {
pl_paragraph *paragraphLayout = obj->fParagraphLayout[p];
if (paragraphLayout != NULL) {
pl_reflow(paragraphLayout);
while ((line = pl_nextLine(paragraphLayout, lineWidth)) != NULL) {
addLine(obj, line);
}
} else {
addLine(obj, NULL);
}
}
}
void pf_draw(pf_flow *flow, rs_surface *surface, le_int32 firstLine, le_int32 lastLine)
{
pf_object *obj = (pf_object *) flow;
le_int32 li, x, y;
x = MARGIN;
y = obj->fAscent;
for (li = firstLine; li <= lastLine; li += 1) {
const pl_line *line = obj->fLines[li];
if (line != NULL) {
le_int32 runCount = pl_countLineRuns(line);
le_int32 run;
if (obj->fParagraphLevel == UBIDI_RTL) {
le_int32 lastX = pl_getLineWidth(line);
x = (obj->fWidth - lastX - MARGIN);
}
for (run = 0; run < runCount; run += 1) {
const pl_visualRun *visualRun = pl_getLineVisualRun(line, run);
le_int32 glyphCount = pl_getVisualRunGlyphCount(visualRun);
const le_font *font = pl_getVisualRunFont(visualRun);
const LEGlyphID *glyphs = pl_getVisualRunGlyphs(visualRun);
const float *positions = pl_getVisualRunPositions(visualRun);
rs_drawGlyphs(surface, font, glyphs, glyphCount, positions, x, y, obj->fWidth, obj->fHeight);
}
}
y += obj->fLineHeight;
}
}
pf_flow *pf_factory(const char *fileName, const le_font *font, gs_guiSupport *guiSupport)
{
LEErrorCode status = LE_NO_ERROR;
le_int32 charCount;
const UChar *text = uc_readFile(fileName, guiSupport, &charCount);
pl_fontRuns *fontRuns;
pf_flow *result = NULL;
if (text == NULL) {
return NULL;
}
fontRuns = pl_openEmptyFontRuns(0);
pl_addFontRun(fontRuns, font, charCount);
result = pf_create(text, charCount, fontRuns, &status);
if (LE_FAILURE(status)) {
pf_close(result);
result = NULL;
}
pl_closeFontRuns(fontRuns);
DELETE_ARRAY(text);
return result;
}

View File

@ -0,0 +1,33 @@
/*
*
* (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
*
*/
#ifndef __PFLOW_H
#define __PFLOW_H
#include "unicode/utypes.h"
#include "layout/LETypes.h"
#include "layout/plruns.h"
#include "layout/playout.h"
#include "gsupport.h"
#include "rsurface.h"
typedef void pf_flow;
pf_flow *pf_create(const LEUnicode chars[], le_int32 charCount, const pl_fontRuns *fontRuns, LEErrorCode *status);
void pf_close(pf_flow *flow);
le_int32 pf_getAscent(pf_flow *flow);
le_int32 pf_getLineHeight(pf_flow *flow);
le_int32 pf_getLineCount(pf_flow *flow);
void pf_breakLines(pf_flow *flow, le_int32 width, le_int32 height);
void pf_draw(pf_flow *flow, rs_surface *surface, le_int32 firstLine, le_int32 lastLine);
pf_flow *pf_factory(const char *fileName, const le_font *font, gs_guiSupport *guiSupport);
#endif

View File

@ -0,0 +1,24 @@
/*
*
* (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
*
*/
#include "loengine.h"
#include "rsurface.h"
#include "LETypes.h"
#include "LEFontInstance.h"
#include "RenderingSurface.h"
U_CDECL_BEGIN
void rs_drawGlyphs(rs_surface *surface, const le_font *font, const LEGlyphID *glyphs, le_int32 count,
const float *positions, le_int32 x, le_int32 y, le_int32 width, le_int32 height)
{
RenderingSurface *rs = (RenderingSurface *) surface;
rs->drawGlyphs((const LEFontInstance *) font, glyphs, count, positions, x, y, width, height);
}
U_CDECL_END

View File

@ -0,0 +1,21 @@
/*
*
* (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
*
*/
#ifndef __RSURFACE_H
#define __RSURFACE_H
#include "loengine.h"
typedef void rs_surface;
U_CDECL_BEGIN
void rs_drawGlyphs(rs_surface *surface, const le_font *font, const LEGlyphID *glyphs, le_int32 count,
const float *positions, le_int32 x, le_int32 y, le_int32 width, le_int32 height);
U_CDECL_END
#endif

View File

@ -0,0 +1,20 @@
/*
*
* (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
*
*/
#include "unicode/utypes.h"
#include "ucreader.h"
#include "gsupport.h"
#include "UnicodeReader.h"
U_CDECL_BEGIN
const UChar *uc_readFile(const char *fileName, gs_guiSupport *guiSupport, int32_t *charCount)
{
return UnicodeReader::readFile(fileName, (GUISupport *) guiSupport, *charCount);
}
U_CDECL_END

View File

@ -0,0 +1,19 @@
/*
*
* (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
*
*/
#ifndef __UCREADER_H
#define __UCREADER_H
#include "unicode/utypes.h"
#include "gsupport.h"
U_CDECL_BEGIN
const UChar *uc_readFile(const char *fileName, gs_guiSupport *guiSupport, int32_t *charCount);
U_CDECL_END
#endif

View File

@ -1,5 +1,5 @@
## Makefile.in for ICU - test/letest ## Makefile.in for ICU - test/letest
## Copyright (c) 2001-2006, International Business Machines Corporation and ## Copyright (c) 2001-2007, International Business Machines Corporation and
## others. All Rights Reserved. ## others. All Rights Reserved.
## Source directory information ## Source directory information
@ -20,8 +20,8 @@ subdir = test/letest
CLEANFILES = *~ $(DEPS) CLEANFILES = *~ $(DEPS)
## Target information ## Target information
TESTTARGET = letest TESTTARGET = letest
GENTARGET = gendata GENTARGET = gendata
BUILDDIR := $(CURR_SRCCODE_FULL_DIR)/../../ BUILDDIR := $(CURR_SRCCODE_FULL_DIR)/../../
# Simplify the path for Unix # Simplify the path for Unix
@ -41,6 +41,7 @@ LIBS = $(LIBICULE) $(LIBICUUC) $(LIBICUI18N) $(LIBCTESTFW) $(LIBICUTOOLUTIL) @LI
COMMONOBJECTS = letsutil.o cmaps.o FontTableCache.o SimpleFontInstance.o PortableFontInstance.o COMMONOBJECTS = letsutil.o cmaps.o FontTableCache.o SimpleFontInstance.o PortableFontInstance.o
TESTOBJECTS = letest.o TESTOBJECTS = letest.o
CTESTOBJECTS = cfonts.o xmlreader.o cletest.o
GENOBJECTS = gendata.o GENOBJECTS = gendata.o
OBJECTS = $(COMMONOBJECTS) $(TESTOBJECTS) $(GENOBJECTS) OBJECTS = $(COMMONOBJECTS) $(TESTOBJECTS) $(GENOBJECTS)
@ -70,7 +71,7 @@ dist-local:
clean-local: clean-local:
test -z "$(CLEANFILES)" || $(RMV) $(CLEANFILES) test -z "$(CLEANFILES)" || $(RMV) $(CLEANFILES)
$(RMV) $(OBJECTS) $(TARGET) $(RMV) $(COMMONOBJECTS) $(TESTOBJECTS) $(CTESTOBJECTS) $(GENOBJECTS) $(TARGET)
distclean-local: clean-local distclean-local: clean-local
$(RMV) Makefile $(RMV) Makefile
@ -82,7 +83,7 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \ cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
$(TESTTARGET) : $(COMMONOBJECTS) $(TESTOBJECTS) $(TESTTARGET) : $(COMMONOBJECTS) $(TESTOBJECTS) $(CTESTOBJECTS)
$(LINK.cc) -o $@ $^ $(LIBS) $(LINK.cc) -o $@ $^ $(LIBS)
$(POST_BUILD_STEP) $(POST_BUILD_STEP)

View File

@ -0,0 +1,55 @@
/*
*
* (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "loengine.h"
#include "PortableFontInstance.h"
#include "SimpleFontInstance.h"
U_CDECL_BEGIN
le_font *le_portableFontOpen(const char *fileName,
float pointSize,
LEErrorCode *status)
{
return (le_font *) new PortableFontInstance(fileName, pointSize, *status);
}
le_font *le_simpleFontOpen(float pointSize,
LEErrorCode *status)
{
return (le_font *) new SimpleFontInstance(pointSize, *status);
}
void le_fontClose(le_font *font)
{
LEFontInstance *fontInstance = (LEFontInstance *) font;
delete fontInstance;
}
const char *le_getNameString(le_font *font, le_uint16 nameID, le_uint16 platform, le_uint16 encoding, le_uint16 language)
{
PortableFontInstance *pfi = (PortableFontInstance *) font;
return pfi->getNameString(nameID, platform, encoding, language);
}
void le_deleteNameString(le_font *font, const char *name)
{
PortableFontInstance *pfi = (PortableFontInstance *) font;
pfi->deleteNameString(name);
}
le_uint32 le_getFontChecksum(le_font *font)
{
PortableFontInstance *pfi = (PortableFontInstance *) font;
return pfi->getFontChecksum();
}
U_CDECL_END

View File

@ -0,0 +1,28 @@
/*
*
* (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
*
*/
#ifndef __CFONTS_H
#define __CFONTS_H
#include "LETypes.h"
#include "loengine.h"
le_font *le_portableFontOpen(const char *fileName,
float pointSize,
LEErrorCode *status);
le_font *le_simpleFontOpen(float pointSize,
LEErrorCode *status);
void le_fontClose(le_font *font);
const char *le_getNameString(le_font *font, le_uint16 nameID, le_uint16 platform, le_uint16 encoding, le_uint16 language);
void le_deleteNameString(le_font *font, const char *name);
le_uint32 le_getFontChecksum(le_font *font);
#endif

View File

@ -0,0 +1,489 @@
/*
*******************************************************************************
*
* Copyright (C) 1999-2007, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
*/
#include "unicode/utypes.h"
#include "unicode/ubidi.h"
#include "unicode/uscript.h"
#include "unicode/ctest.h"
#include "layout/LETypes.h"
#include "layout/LEScripts.h"
#include "loengine.h"
#include "cfonts.h"
#include "letest.h"
#include "sfnt.h"
#include "xmlreader.h"
#include "putilimp.h" /* for U_FILE_SEP_STRING */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define CH_COMMA 0x002C
U_CDECL_BEGIN
static void U_CALLCONV ParamTest(void)
{
LEErrorCode status = LE_NO_ERROR;
le_font *font = le_simpleFontOpen(12, &status);
le_engine *engine = le_create(font, arabScriptCode, -1, 0, &status);
LEGlyphID *glyphs = NULL;
le_int32 *indices = NULL;
float *positions = NULL;
le_int32 glyphCount = 0;
float x = 0.0, y = 0.0;
LEUnicode chars[] = {
0x0045, 0x006E, 0x0067, 0x006C, 0x0069, 0x0073, 0x0068, 0x0020, /* "English " */
0x0645, 0x0627, 0x0646, 0x062A, 0x0648, 0x0634, /* MEM ALIF KAF NOON TEH WAW SHEEN */
0x0020, 0x0074, 0x0065, 0x0078, 0x0074, 0x02E /* " text." */
};
glyphCount = le_getGlyphCount(engine, &status);
if (glyphCount != 0) {
log_err("Calling getGlyphCount() on an empty layout returned %d.\n", glyphCount);
}
glyphs = NEW_ARRAY(LEGlyphID, glyphCount + 10);
indices = NEW_ARRAY(le_int32, glyphCount + 10);
positions = NEW_ARRAY(float, glyphCount + 10);
le_getGlyphs(engine, NULL, &status);
if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
log_err("Calling getGlyphs(NULL, status) did not return LE_ILLEGAL_ARGUMENT_ERROR.\n");
}
status = LE_NO_ERROR;
le_getGlyphs(engine, glyphs, &status);
if (status != LE_NO_LAYOUT_ERROR) {
log_err("Calling getGlyphs(glyphs, status) on an empty layout did not return LE_NO_LAYOUT_ERROR.\n");
}
status = LE_NO_ERROR;
le_getCharIndices(engine, NULL, &status);
if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
log_err("Calling getCharIndices(NULL, status) did not return LE_ILLEGAL_ARGUMENT_ERROR.\n");
}
status = LE_NO_ERROR;
le_getCharIndices(engine, indices, &status);
if (status != LE_NO_LAYOUT_ERROR) {
log_err("Calling getCharIndices(indices, status) on an empty layout did not return LE_NO_LAYOUT_ERROR.\n");
}
status = LE_NO_ERROR;
le_getCharIndicesWithBase(engine, NULL, 1024, &status);
if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
log_err("Calling getCharIndices(NULL, 1024, status) did not return LE_ILLEGAL_ARGUMENT_ERROR.\n");
}
status = LE_NO_ERROR;
le_getCharIndicesWithBase(engine, indices, 1024, &status);
if (status != LE_NO_LAYOUT_ERROR) {
log_err("Calling getCharIndices(indices, 1024, status) on an empty layout did not return LE_NO_LAYOUT_ERROR.\n");
}
status = LE_NO_ERROR;
le_getGlyphPositions(engine, NULL, &status);
if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
log_err("Calling getGlyphPositions(NULL, status) did not return LE_ILLEGAL_ARGUMENT_ERROR.\n");
}
status = LE_NO_ERROR;
le_getGlyphPositions(engine, positions, &status);
if (status != LE_NO_LAYOUT_ERROR) {
log_err("Calling getGlyphPositions(positions, status) on an empty layout did not return LE_NO_LAYOUT_ERROR.\n");
}
DELETE_ARRAY(positions);
DELETE_ARRAY(indices);
DELETE_ARRAY(glyphs);
status = LE_NO_ERROR;
glyphCount = le_layoutChars(engine, NULL, 0, 0, 0, FALSE, 0.0, 0.0, &status);
if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
log_err("Calling layoutChars(NULL, 0, 0, 0, FALSE, 0.0, 0.0, status) did not fail w/ LE_ILLEGAL_ARGUMENT_ERROR.\n");
}
status = LE_NO_ERROR;
glyphCount = le_layoutChars(engine, chars, -1, 6, 20, TRUE, 0.0, 0.0, &status);
if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
log_err("Calling layoutChars(chars, -1, 6, 20, TRUE, 0.0, 0.0, status) did not fail w/ LE_ILLEGAL_ARGUMENT_ERROR.\n");
}
status = LE_NO_ERROR;
glyphCount = le_layoutChars(engine, chars, 8, -1, 20, TRUE, 0.0, 0.0, &status);
if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
log_err("Calling layoutChars(chars, 8, -1, 20, TRUE, 0.0, 0.0, status) did not fail w/ LE_ILLEGAL_ARGUMENT_ERROR.\n");
}
status = LE_NO_ERROR;
glyphCount = le_layoutChars(engine, chars, 8, 6, -1, TRUE, 0.0, 0.0, &status);
if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
log_err("Calling layoutChars((chars, 8, 6, -1, TRUE, 0.0, 0.0, status) did not fail w/ LE_ILLEGAL_ARGUMENT_ERROR.\n");
}
status = LE_NO_ERROR;
glyphCount = le_layoutChars(engine, chars, 8, 6, 10, TRUE, 0.0, 0.0, &status);
if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
log_err("Calling layoutChars(chars, 8, 6, 10, TRUE, 0.0, 0.0, status) did not fail w/ LE_ILLEGAL_ARGUMENT_ERROR.\n");
}
status = LE_NO_ERROR;
glyphCount = le_layoutChars(engine, chars, 8, 6, 20, TRUE, 0.0, 0.0, &status);
if (LE_FAILURE(status)) {
log_err("Calling layoutChars(chars, 8, 6, 20, TRUE, 0.0, 0.0, status) failed.\n");
goto bail;
}
le_getGlyphPosition(engine, -1, &x, &y, &status);
if (status != LE_INDEX_OUT_OF_BOUNDS_ERROR) {
log_err("Calling getGlyphPosition(-1, x, y, status) did not fail w/ LE_INDEX_OUT_OF_BOUNDS_ERROR.\n");
}
status = LE_NO_ERROR;
le_getGlyphPosition(engine, glyphCount + 1, &x, &y, &status);
if (status != LE_INDEX_OUT_OF_BOUNDS_ERROR) {
log_err("Calling getGlyphPosition(glyphCount + 1, x, y, status) did not fail w/ LE_INDEX_OUT_OF_BOUNDS_ERROR.\n");
}
bail:
le_close(engine);
le_fontClose(font);
}
U_CDECL_END
U_CDECL_BEGIN
static void U_CALLCONV FactoryTest(void)
{
LEErrorCode status = LE_NO_ERROR;
le_font *font = le_simpleFontOpen(12, &status);
le_engine *engine = NULL;
le_int32 scriptCode;
for(scriptCode = 0; scriptCode < scriptCodeCount; scriptCode += 1) {
status = LE_NO_ERROR;
engine = le_create(font, scriptCode, -1, 0, &status);
if (LE_FAILURE(status)) {
log_err("Could not create a LayoutEngine for script \'%s\'.\n", uscript_getShortName((UScriptCode)scriptCode));
}
le_close(engine);
}
le_fontClose(font);
}
U_CDECL_END
U_CDECL_BEGIN
static void U_CALLCONV AccessTest(void)
{
LEErrorCode status = LE_NO_ERROR;
le_font *font = le_simpleFontOpen(12, &status);
le_engine *engine =le_create(font, arabScriptCode, -1, 0, &status);
le_int32 glyphCount;
LEGlyphID glyphs[6];
le_int32 biasedIndices[6], indices[6], glyph;
float positions[6 * 2 + 2];
LEUnicode chars[] = {
0x0045, 0x006E, 0x0067, 0x006C, 0x0069, 0x0073, 0x0068, 0x0020, /* "English " */
0x0645, 0x0627, 0x0646, 0x062A, 0x0648, 0x0634, /* MEM ALIF KAF NOON TEH WAW SHEEN */
0x0020, 0x0074, 0x0065, 0x0078, 0x0074, 0x02E /* " text." */
};
if (LE_FAILURE(status)) {
log_err("Could not create LayoutEngine.\n");
goto bail;
}
glyphCount = le_layoutChars(engine, chars, 8, 6, 20, TRUE, 0.0, 0.0, &status);
if (LE_FAILURE(status) || glyphCount != 6) {
log_err("layoutChars(chars, 8, 6, 20, TRUE, 0.0, 0.0, status) failed.\n");
goto bail;
}
le_getGlyphs(engine, glyphs, &status);
le_getCharIndices(engine, indices, &status);
le_getGlyphPositions(engine, positions, &status);
if (LE_FAILURE(status)) {
log_err("Could not get glyph, indices and position arrays.\n");
goto bail;
}
status = LE_NO_ERROR;
le_getCharIndicesWithBase(engine, biasedIndices, 1024, &status);
if (LE_FAILURE(status)) {
log_err("getCharIndices(biasedIndices, 1024, status) failed.\n");
} else {
for (glyph = 0; glyph < glyphCount; glyph += 1) {
if (biasedIndices[glyph] != (indices[glyph] + 1024)) {
log_err("biasedIndices[%d] != indices[%d] + 1024: %8X, %8X\n",
glyph, glyph, biasedIndices[glyph], indices[glyph]);
break;
}
}
}
status = LE_NO_ERROR;
for (glyph = 0; glyph <= glyphCount; glyph += 1) {
float x = 0.0, y = 0.0;
le_getGlyphPosition(engine, glyph, &x, &y, &status);
if (LE_FAILURE(status)) {
log_err("getGlyphPosition(%d, x, y, status) failed.\n", glyph);
break;
}
if (x != positions[glyph*2] || y != positions[glyph*2 + 1]) {
log_err("getGlyphPosition(%d, x, y, status) returned bad position: (%f, %f) != (%f, %f)\n",
glyph, x, y, positions[glyph*2], positions[glyph*2 + 1]);
break;
}
}
bail:
le_close(engine);
le_fontClose(font);
}
U_CDECL_END
static le_bool compareResults(const char *testID, TestResult *expected, TestResult *actual)
{
le_int32 i;
/* NOTE: we'll stop on the first failure 'cause once there's one error, it may cascade... */
if (actual->glyphCount != expected->glyphCount) {
log_err("Test %s: incorrect glyph count: exptected %d, got %d\n",
testID, expected->glyphCount, actual->glyphCount);
return FALSE;
}
for (i = 0; i < actual->glyphCount; i += 1) {
if (actual->glyphs[i] != expected->glyphs[i]) {
log_err("Test %s: incorrect id for glyph %d: expected %4X, got %4X\n",
testID, i, expected->glyphs[i], actual->glyphs[i]);
return FALSE;
}
}
for (i = 0; i < actual->glyphCount; i += 1) {
if (actual->indices[i] != expected->indices[i]) {
log_err("Test %s: incorrect index for glyph %d: expected %8X, got %8X\n",
testID, i, expected->indices[i], actual->indices[i]);
return FALSE;
}
}
for (i = 0; i <= actual->glyphCount; i += 1) {
double xError = uprv_fabs(actual->positions[i * 2] - expected->positions[i * 2]);
double yError = uprv_fabs(actual->positions[i * 2 + 1] - expected->positions[i * 2 + 1]);
if (xError > 0.0001) {
log_err("Test %s: incorrect x position for glyph %d: expected %f, got %f\n",
testID, i, expected->positions[i * 2], actual->positions[i * 2]);
return FALSE;
}
if (yError < 0) {
yError = -yError;
}
if (yError > 0.0001) {
log_err("Test %s: incorrect y position for glyph %d: expected %f, got %f\n",
testID, i, expected->positions[i * 2 + 1], actual->positions[i * 2 + 1]);
return FALSE;
}
}
return TRUE;
}
static void checkFontVersion(le_font *font, const char *testVersionString,
le_uint32 testChecksum, const char *testID)
{
le_uint32 fontChecksum = le_getFontChecksum(font);
if (fontChecksum != testChecksum) {
const char *fontVersionString = le_getNameString(font, NAME_VERSION_STRING,
PLATFORM_MACINTOSH, MACINTOSH_ROMAN, MACINTOSH_ENGLISH);
log_info("Test %s: this may not be the same font used to generate the test data.\n", testID);
log_info("Your font's version string is \"%s\"\n", fontVersionString);
log_info("The expected version string is \"%s\"\n", testVersionString);
log_info("If you see errors, they may be due to the version of the font you're using.\n");
le_deleteNameString(font, fontVersionString);
}
}
/* Returns the path to icu/source/test/testdata/ */
static const char *getSourceTestData() {
#ifdef U_TOPSRCDIR
const char *srcDataDir = U_TOPSRCDIR U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
#else
const char *srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
FILE *f = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"rbbitst.txt", "r");
if (f != NULL) {
/* We're in icu/source/test/letest/ */
fclose(f);
} else {
/* We're in icu/source/test/letest/(Debug|Release) */
srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
}
#endif
return srcDataDir;
}
static const char *getPath(char buffer[2048], const char *filename) {
const char *testDataDirectory = getSourceTestData();
strcpy(buffer, testDataDirectory);
strcat(buffer, filename);
return buffer;
}
static le_font *openFont(const char *fontName, const char *checksum, const char *version, const char *testID)
{
char path[2048];
le_font *font;
LEErrorCode fontStatus = LE_NO_ERROR;
if (fontName != NULL) {
font = le_portableFontOpen(getPath(path, fontName), 12, &fontStatus);
if (LE_FAILURE(fontStatus)) {
log_info("Test %s: can't open font %s - test skipped.\n", testID, fontName);
le_fontClose(font);
return NULL;
} else {
le_uint32 cksum = 0;
sscanf(checksum, "%x", &cksum);
checkFontVersion(font, version, cksum, testID);
}
} else {
font = le_simpleFontOpen(12, &fontStatus);
}
return font;
}
static le_bool getRTL(const LEUnicode *text, le_int32 charCount)
{
UBiDiLevel paraLevel;
UErrorCode status = U_ZERO_ERROR;
UBiDi *ubidi = ubidi_openSized(charCount, 0, &status);
ubidi_setPara(ubidi, text, charCount, UBIDI_DEFAULT_LTR, NULL, &status);
paraLevel = ubidi_getParaLevel(ubidi);
ubidi_close(ubidi);
return paraLevel & 1;
}
static void doTestCase (const char *testID,
const char *fontName,
const char *fontVersion,
const char *fontChecksum,
le_int32 scriptCode,
le_int32 languageCode,
const LEUnicode *text,
le_int32 charCount,
TestResult *expected)
{
LEErrorCode status = LE_NO_ERROR;
le_engine *engine;
le_font *font = openFont(fontName, fontChecksum, fontVersion, testID);
le_int32 typoFlags = 3; /* kerning + ligatures */
TestResult actual;
if (font == NULL) {
/* error message already printed. */
return;
}
if (fontName == NULL) {
typoFlags |= 0x80000000L; /* use CharSubstitutionFilter... */
}
engine = le_create(font, scriptCode, languageCode, typoFlags, &status);
if (LE_FAILURE(status)) {
log_err("Test %s: could not create a LayoutEngine.\n", testID);
goto free_expected;
}
actual.glyphCount = le_layoutChars(engine, text, 0, charCount, charCount, getRTL(text, charCount), 0, 0, &status);
actual.glyphs = NEW_ARRAY(LEGlyphID, actual.glyphCount);
actual.indices = NEW_ARRAY(le_int32, actual.glyphCount);
actual.positions = NEW_ARRAY(float, actual.glyphCount * 2 + 2);
le_getGlyphs(engine, actual.glyphs, &status);
le_getCharIndices(engine, actual.indices, &status);
le_getGlyphPositions(engine, actual.positions, &status);
compareResults(testID, expected, &actual);
DELETE_ARRAY(actual.positions);
DELETE_ARRAY(actual.indices);
DELETE_ARRAY(actual.glyphs);
le_close(engine);
free_expected:
le_fontClose(font);
}
static void U_CALLCONV DataDrivenTest(void)
{
char path[2048];
const char *testFilePath = getPath(path, "letest.xml");
readTestFile(testFilePath, doTestCase);
}
U_CFUNC void addCTests(TestNode **root)
{
addTest(root, &ParamTest, "c_api/ParameterTest");
addTest(root, &FactoryTest, "c_api/FactoryTest");
addTest(root, &AccessTest, "c_layout/AccessTest");
addTest(root, &DataDrivenTest, "c_layout/DataDrivenTest");
}

View File

@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cletest", "cletest.vcproj", "{798E3AE4-A984-43FF-8928-EACFF43F56AE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{798E3AE4-A984-43FF-8928-EACFF43F56AE}.Debug|Win32.ActiveCfg = Debug|Win32
{798E3AE4-A984-43FF-8928-EACFF43F56AE}.Debug|Win32.Build.0 = Debug|Win32
{798E3AE4-A984-43FF-8928-EACFF43F56AE}.Release|Win32.ActiveCfg = Release|Win32
{798E3AE4-A984-43FF-8928-EACFF43F56AE}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,273 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="cletest"
ProjectGUID="{798E3AE4-A984-43FF-8928-EACFF43F56AE}"
RootNamespace="cletest"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\include\layout;..\..\..\include;..\..\common;..\..\tools\ctestfw;..\..\tools\toolutil;..\..\layout"
PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="..\..\..\lib\icuucd.lib ..\..\..\lib\icuind.lib ..\..\..\lib\icutestd.lib ..\..\..\lib\icutud.lib ..\..\..\lib\iculed.lib"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="0"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\..\include\layout;..\..\..\include;..\..\common;..\..\tools\ctestfw;..\..\tools\toolutil;..\..\layout"
PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="..\..\..\lib\icuuc.lib ..\..\..\lib\icuin.lib ..\..\..\lib\icutest.lib ..\..\..\lib\icutu.lib ..\..\..\lib\icule.lib"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="0"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\cfonts.cpp"
>
</File>
<File
RelativePath=".\cletest.c"
>
</File>
<File
RelativePath=".\cmaps.cpp"
>
</File>
<File
RelativePath=".\FontObject.cpp"
>
</File>
<File
RelativePath=".\FontTableCache.cpp"
>
</File>
<File
RelativePath=".\letsutil.cpp"
>
</File>
<File
RelativePath=".\PortableFontInstance.cpp"
>
</File>
<File
RelativePath=".\SimpleFontInstance.cpp"
>
</File>
<File
RelativePath=".\xmlreader.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\cfonts.h"
>
</File>
<File
RelativePath=".\cmaps.h"
>
</File>
<File
RelativePath=".\FontObject.h"
>
</File>
<File
RelativePath=".\FontTableCache.h"
>
</File>
<File
RelativePath=".\letest.h"
>
</File>
<File
RelativePath=".\letsutil.h"
>
</File>
<File
RelativePath=".\PortableFontInstance.h"
>
</File>
<File
RelativePath=".\sfnt.h"
>
</File>
<File
RelativePath=".\SimpleFontInstance.h"
>
</File>
<File
RelativePath=".\xmlreader.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -1,7 +1,7 @@
/* /*
******************************************************************************* *******************************************************************************
* *
* Copyright (C) 1999-2006, International Business Machines * Copyright (C) 1999-2007, International Business Machines
* Corporation and others. All Rights Reserved. * Corporation and others. All Rights Reserved.
* *
******************************************************************************* *******************************************************************************
@ -657,7 +657,7 @@ static void U_CALLCONV DataDrivenTest(void)
expected.glyphCount = glyphCount; expected.glyphCount = glyphCount;
if (glyphCount < charCount || indexCount != glyphCount || positionCount < glyphCount * 2 + 2) { if (glyphCount < charCount || indexCount != glyphCount || positionCount < glyphCount * 2 + 2) {
log_err("Test %s: inconsistent input data: charCount = %d, glyphCount = %d, glyphCount = %d, indexCount = %d, positionCount = %d\n", log_err("Test %s: inconsistent input data: charCount = %d, glyphCount = %d, indexCount = %d, positionCount = %d\n",
id, charCount, glyphCount, indexCount, positionCount); id, charCount, glyphCount, indexCount, positionCount);
goto free_expected; goto free_expected;
}; };
@ -707,12 +707,14 @@ free_c_strings:
} }
U_CDECL_END U_CDECL_END
static void addAllTests(TestNode** root) static void addAllTests(TestNode **root)
{ {
addTest(root, &ParamTest, "api/ParameterTest"); addTest(root, &ParamTest, "api/ParameterTest");
addTest(root, &FactoryTest, "api/FactoryTest"); addTest(root, &FactoryTest, "api/FactoryTest");
addTest(root, &AccessTest, "layout/AccessTest"); addTest(root, &AccessTest, "layout/AccessTest");
addTest(root, &DataDrivenTest, "layout/DataDrivenTest"); addTest(root, &DataDrivenTest, "layout/DataDrivenTest");
addCTests(root);
} }
/* returns the path to icu/source/data/out */ /* returns the path to icu/source/data/out */

View File

@ -15,6 +15,7 @@
#define __LETEST_H #define __LETEST_H
#include "LETypes.h" #include "LETypes.h"
#include "unicode/ctest.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -38,4 +39,11 @@ struct TestResult
le_int32 *indices; le_int32 *indices;
float *positions; float *positions;
}; };
#ifndef XP_CPLUSPLUS
typedef struct TestResult TestResult;
#endif
U_CFUNC void addCTests(TestNode **root);
#endif #endif

View File

@ -201,6 +201,14 @@
Name="Source Files" Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
> >
<File
RelativePath=".\cfonts.cpp"
>
</File>
<File
RelativePath=".\cletest.c"
>
</File>
<File <File
RelativePath=".\cmaps.cpp" RelativePath=".\cmaps.cpp"
> >
@ -225,11 +233,19 @@
RelativePath=".\SimpleFontInstance.cpp" RelativePath=".\SimpleFontInstance.cpp"
> >
</File> </File>
<File
RelativePath=".\xmlreader.cpp"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="Header Files" Name="Header Files"
Filter="h;hpp;hxx;hm;inl" Filter="h;hpp;hxx;hm;inl"
> >
<File
RelativePath=".\cfonts.h"
>
</File>
<File <File
RelativePath=".\cmaps.h" RelativePath=".\cmaps.h"
> >
@ -258,6 +274,10 @@
RelativePath=".\SimpleFontInstance.h" RelativePath=".\SimpleFontInstance.h"
> >
</File> </File>
<File
RelativePath=".\xmlreader.h"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="Resource Files" Name="Resource Files"

View File

@ -24,6 +24,10 @@ struct DirectoryEntry
le_uint32 length; le_uint32 length;
}; };
#ifndef XP_CPLUSPLUS
typedef struct DirectoryEntry DirectoryEntry;
#endif
struct SFNTDirectory struct SFNTDirectory
{ {
le_uint32 scalerType; le_uint32 scalerType;
@ -34,6 +38,10 @@ struct SFNTDirectory
DirectoryEntry tableDirectory[ANY_NUMBER]; DirectoryEntry tableDirectory[ANY_NUMBER];
}; };
#ifndef XP_CPLUSPLUS
typedef struct SFNTDirectory SFNTDirectory;
#endif
struct CMAPEncodingSubtableHeader struct CMAPEncodingSubtableHeader
{ {
@ -42,6 +50,10 @@ struct CMAPEncodingSubtableHeader
le_uint32 encodingOffset; le_uint32 encodingOffset;
}; };
#ifndef XP_CPLUSPLUS
typedef struct CMAPEncodingSubtableHeader CMAPEncodingSubtableHeader;
#endif
struct CMAPTable struct CMAPTable
{ {
le_uint16 version; le_uint16 version;
@ -49,6 +61,10 @@ struct CMAPTable
CMAPEncodingSubtableHeader encodingSubtableHeaders[ANY_NUMBER]; CMAPEncodingSubtableHeader encodingSubtableHeaders[ANY_NUMBER];
}; };
#ifndef XP_CPLUSPLUS
typedef struct CMAPTable CMAPTable;
#endif
struct CMAPEncodingSubtable struct CMAPEncodingSubtable
{ {
le_uint16 format; le_uint16 format;
@ -56,10 +72,25 @@ struct CMAPEncodingSubtable
le_uint16 language; le_uint16 language;
}; };
#ifndef XP_CPLUSPLUS
typedef struct CMAPEncodingSubtable CMAPEncodingSubtable;
#endif
#ifdef XP_CPLUSPLUS
struct CMAPFormat0Encoding : CMAPEncodingSubtable struct CMAPFormat0Encoding : CMAPEncodingSubtable
{ {
le_uint8 glyphIndexArray[256]; le_uint8 glyphIndexArray[256];
}; };
#else
struct CMAPFormat0Encoding
{
CMAPEncodingSubtable base;
le_uint8 glyphIndexArray[256];
};
typedef struct CMAPFormat0Encoding CMAPFormat0Encoding;
#endif
struct CMAPFormat2Subheader struct CMAPFormat2Subheader
{ {
@ -69,12 +100,29 @@ struct CMAPFormat2Subheader
le_uint16 idRangeOffset; le_uint16 idRangeOffset;
}; };
#ifndef XP_CPLUSPLUS
typedef struct CMAPFormat2Subheader CMAPFormat2Subheader;
#endif
#ifdef XP_CPLUSPLUS
struct CMAPFormat2Encoding : CMAPEncodingSubtable struct CMAPFormat2Encoding : CMAPEncodingSubtable
{ {
le_uint16 subHeadKeys[256]; le_uint16 subHeadKeys[256];
CMAPFormat2Subheader subheaders[ANY_NUMBER]; CMAPFormat2Subheader subheaders[ANY_NUMBER];
}; };
#else
struct CMAPFormat2Encoding
{
CMAPEncodingSubtable base;
le_uint16 subHeadKeys[256];
CMAPFormat2Subheader subheaders[ANY_NUMBER];
};
typedef struct CMAPFormat2Encoding CMAPFormat2Encoding;
#endif
#ifdef XP_CPLUSPLUS
struct CMAPFormat4Encoding : CMAPEncodingSubtable struct CMAPFormat4Encoding : CMAPEncodingSubtable
{ {
le_uint16 segCountX2; le_uint16 segCountX2;
@ -82,19 +130,55 @@ struct CMAPFormat4Encoding : CMAPEncodingSubtable
le_uint16 entrySelector; le_uint16 entrySelector;
le_uint16 rangeShift; le_uint16 rangeShift;
le_uint16 endCodes[ANY_NUMBER]; le_uint16 endCodes[ANY_NUMBER];
/*
le_uint16 reservedPad;
le_uint16 startCodes[ANY_NUMBER];
le_uint16 idDelta[ANY_NUMBER];
le_uint16 idRangeOffset[ANY_NUMBER];
le_uint16 glyphIndexArray[ANY_NUMBER];
*/
};
#else
struct CMAPFormat4Encoding
{
CMAPEncodingSubtable base;
le_uint16 segCountX2;
le_uint16 searchRange;
le_uint16 entrySelector;
le_uint16 rangeShift;
le_uint16 endCodes[ANY_NUMBER];
/*
// le_uint16 reservedPad; // le_uint16 reservedPad;
// le_uint16 startCodes[ANY_NUMBER]; // le_uint16 startCodes[ANY_NUMBER];
// le_uint16 idDelta[ANY_NUMBER]; // le_uint16 idDelta[ANY_NUMBER];
// le_uint16 idRangeOffset[ANY_NUMBER]; // le_uint16 idRangeOffset[ANY_NUMBER];
// le_uint16 glyphIndexArray[ANY_NUMBER]; // le_uint16 glyphIndexArray[ANY_NUMBER];
*/
}; };
typedef struct CMAPFormat4Encoding CMAPFormat4Encoding;
#endif
#ifdef XP_CPLUSPLUS
struct CMAPFormat6Encoding : CMAPEncodingSubtable struct CMAPFormat6Encoding : CMAPEncodingSubtable
{ {
le_uint16 firstCode; le_uint16 firstCode;
le_uint16 entryCount; le_uint16 entryCount;
le_uint16 glyphIndexArray[ANY_NUMBER]; le_uint16 glyphIndexArray[ANY_NUMBER];
}; };
#else
struct CMAPFormat6Encoding
{
CMAPEncodingSubtable base;
le_uint16 firstCode;
le_uint16 entryCount;
le_uint16 glyphIndexArray[ANY_NUMBER];
};
typedef struct CMAPFormat6Encoding CMAPFormat6Encoding;
#endif
struct CMAPEncodingSubtable32 struct CMAPEncodingSubtable32
{ {
@ -103,6 +187,10 @@ struct CMAPEncodingSubtable32
le_uint32 language; le_uint32 language;
}; };
#ifndef XP_CPLUSPLUS
typedef struct CMAPEncodingSubtable32 CMAPEncodingSubtable32;
#endif
struct CMAPGroup struct CMAPGroup
{ {
le_uint32 startCharCode; le_uint32 startCharCode;
@ -110,25 +198,67 @@ struct CMAPGroup
le_uint32 startGlyphCode; le_uint32 startGlyphCode;
}; };
#ifndef XP_CPLUSPLUS
typedef struct CMAPGroup CMAPGroup;
#endif
#ifdef XP_CPLUSPLUS
struct CMAPFormat8Encoding : CMAPEncodingSubtable32 struct CMAPFormat8Encoding : CMAPEncodingSubtable32
{ {
le_uint32 is32[65536/32]; le_uint32 is32[65536/32];
le_uint32 nGroups; le_uint32 nGroups;
CMAPGroup groups[ANY_NUMBER]; CMAPGroup groups[ANY_NUMBER];
}; };
#else
struct CMAPFormat8Encoding
{
CMAPEncodingSubtable32 base;
le_uint32 is32[65536/32];
le_uint32 nGroups;
CMAPGroup groups[ANY_NUMBER];
};
typedef struct CMAPFormat8Encoding CMAPFormat8Encoding;
#endif
#ifdef XP_CPLUSPLUS
struct CMAPFormat10Encoding : CMAPEncodingSubtable32 struct CMAPFormat10Encoding : CMAPEncodingSubtable32
{ {
le_uint32 startCharCode; le_uint32 startCharCode;
le_uint32 numCharCodes; le_uint32 numCharCodes;
le_uint16 glyphs[ANY_NUMBER]; le_uint16 glyphs[ANY_NUMBER];
}; };
#else
struct CMAPFormat10Encoding
{
CMAPEncodingSubtable32 base;
le_uint32 startCharCode;
le_uint32 numCharCodes;
le_uint16 glyphs[ANY_NUMBER];
};
typedef struct CMAPFormat10Encoding CMAPFormat10Encoding;
#endif
#ifdef XP_CPLUSPLUS
struct CMAPFormat12Encoding : CMAPEncodingSubtable32 struct CMAPFormat12Encoding : CMAPEncodingSubtable32
{ {
le_uint32 nGroups; le_uint32 nGroups;
CMAPGroup groups[ANY_NUMBER]; CMAPGroup groups[ANY_NUMBER];
}; };
#else
struct CMAPFormat12Encoding
{
CMAPEncodingSubtable32 base;
le_uint32 nGroups;
CMAPGroup groups[ANY_NUMBER];
};
typedef struct CMAPFormat12Encoding CMAPFormat12Encoding;
#endif
typedef le_int32 fixed; typedef le_int32 fixed;
@ -138,6 +268,10 @@ struct BigDate
le_uint32 ad; le_uint32 ad;
}; };
#ifndef XP_CPLUSPLUS
typedef struct BigDate BigDate;
#endif
struct HEADTable struct HEADTable
{ {
fixed version; fixed version;
@ -158,6 +292,10 @@ struct HEADTable
le_int16 glyphDataFormat; le_int16 glyphDataFormat;
}; };
#ifndef XP_CPLUSPLUS
typedef struct HEADTable HEADTable;
#endif
struct MAXPTable struct MAXPTable
{ {
fixed version; fixed version;
@ -177,6 +315,10 @@ struct MAXPTable
le_uint16 maxComponentDepth; le_uint16 maxComponentDepth;
}; };
#ifndef XP_CPLUSPLUS
typedef struct MAXPTable MAXPTable;
#endif
struct HHEATable struct HHEATable
{ {
fixed version; fixed version;
@ -198,18 +340,30 @@ struct HHEATable
le_uint16 numOfLongHorMetrics; le_uint16 numOfLongHorMetrics;
}; };
#ifndef XP_CPLUSPLUS
typedef struct HHEATable HHEATable;
#endif
struct LongHorMetric struct LongHorMetric
{ {
le_uint16 advanceWidth; le_uint16 advanceWidth;
le_int16 leftSideBearing; le_int16 leftSideBearing;
}; };
#ifndef XP_CPLUSPLUS
typedef struct LongHorMetric LongHorMetric;
#endif
struct HMTXTable struct HMTXTable
{ {
LongHorMetric hMetrics[ANY_NUMBER]; // ANY_NUMBER = numOfLongHorMetrics from hhea table LongHorMetric hMetrics[ANY_NUMBER]; /* ANY_NUMBER = numOfLongHorMetrics from hhea table */
// le_int16 leftSideBearing[ANY_NUMBER]; // ANY_NUMBER = numGlyphs - numOfLongHorMetrics /* le_int16 leftSideBearing[ANY_NUMBER]; ANY_NUMBER = numGlyphs - numOfLongHorMetrics */
}; };
#ifndef XP_CPLUSPLUS
typedef struct HMTXTable HMTXTable;
#endif
enum PlatformID enum PlatformID
{ {
PLATFORM_UNICODE = 0, PLATFORM_UNICODE = 0,
@ -264,6 +418,10 @@ struct NameRecord
le_uint16 offset; le_uint16 offset;
}; };
#ifndef XP_CPLUSPLUS
typedef struct NameRecord NameRecord;
#endif
struct NAMETable struct NAMETable
{ {
le_uint16 version; le_uint16 version;
@ -272,5 +430,9 @@ struct NAMETable
NameRecord nameRecords[ANY_NUMBER]; NameRecord nameRecords[ANY_NUMBER];
}; };
#ifndef XP_CPLUSPLUS
typedef struct NAMETable NAMETable;
#endif
#endif #endif

View File

@ -0,0 +1,259 @@
/*
*******************************************************************************
*
* Copyright (C) 1999-2007, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
*/
#include "unicode/utypes.h"
#include "unicode/uclean.h"
#include "unicode/uchar.h"
#include "unicode/unistr.h"
#include "unicode/uscript.h"
#include "unicode/putil.h"
#include "unicode/ctest.h"
#include "layout/LETypes.h"
#include "layout/LEScripts.h"
#include "letsutil.h"
#include "letest.h"
#include "xmlreader.h"
#include "xmlparser.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
//U_NAMESPACE_USE
#define CH_COMMA 0x002C
static le_uint32 *getHexArray(const UnicodeString &numbers, int32_t &arraySize)
{
int32_t offset = -1;
arraySize = 1;
while((offset = numbers.indexOf(CH_COMMA, offset + 1)) >= 0) {
arraySize += 1;
}
le_uint32 *array = NEW_ARRAY(le_uint32, arraySize);
char number[16];
le_int32 count = 0;
le_int32 start = 0, end = 0;
le_int32 len = 0;
// trim leading whitespace
while(u_isUWhiteSpace(numbers[start])) {
start += 1;
}
while((end = numbers.indexOf(CH_COMMA, start)) >= 0) {
len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV);
number[len] = '\0';
start = end + 1;
sscanf(number, "%x", &array[count++]);
// trim whitespace following the comma
while(u_isUWhiteSpace(numbers[start])) {
start += 1;
}
}
// trim trailing whitespace
end = numbers.length();
while(u_isUWhiteSpace(numbers[end - 1])) {
end -= 1;
}
len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV);
number[len] = '\0';
sscanf(number, "%x", &array[count]);
return array;
}
static float *getFloatArray(const UnicodeString &numbers, int32_t &arraySize)
{
int32_t offset = -1;
arraySize = 1;
while((offset = numbers.indexOf(CH_COMMA, offset + 1)) >= 0) {
arraySize += 1;
}
float *array = NEW_ARRAY(float, arraySize);
char number[32];
le_int32 count = 0;
le_int32 start = 0, end = 0;
le_int32 len = 0;
// trim leading whitespace
while(u_isUWhiteSpace(numbers[start])) {
start += 1;
}
while((end = numbers.indexOf(CH_COMMA, start)) >= 0) {
len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV);
number[len] = '\0';
start = end + 1;
sscanf(number, "%f", &array[count++]);
// trim whiteapce following the comma
while(u_isUWhiteSpace(numbers[start])) {
start += 1;
}
}
while(u_isUWhiteSpace(numbers[start])) {
start += 1;
}
// trim trailing whitespace
end = numbers.length();
while(u_isUWhiteSpace(numbers[end - 1])) {
end -= 1;
}
len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV);
number[len] = '\0';
sscanf(number, "%f", &array[count]);
return array;
}
U_CDECL_BEGIN
void readTestFile(const char *testFilePath, TestCaseCallback callback)
{
#if !UCONFIG_NO_REGULAR_EXPRESSIONS
UErrorCode status = U_ZERO_ERROR;
UXMLParser *parser = UXMLParser::createParser(status);
UXMLElement *root = parser->parseFile(testFilePath, status);
if (root == NULL) {
log_err("Could not open the test data file: %s\n", testFilePath);
delete parser;
return;
}
UnicodeString test_case = UNICODE_STRING_SIMPLE("test-case");
UnicodeString test_text = UNICODE_STRING_SIMPLE("test-text");
UnicodeString test_font = UNICODE_STRING_SIMPLE("test-font");
UnicodeString result_glyphs = UNICODE_STRING_SIMPLE("result-glyphs");
UnicodeString result_indices = UNICODE_STRING_SIMPLE("result-indices");
UnicodeString result_positions = UNICODE_STRING_SIMPLE("result-positions");
// test-case attributes
UnicodeString id_attr = UNICODE_STRING_SIMPLE("id");
UnicodeString script_attr = UNICODE_STRING_SIMPLE("script");
UnicodeString lang_attr = UNICODE_STRING_SIMPLE("lang");
// test-font attributes
UnicodeString name_attr = UNICODE_STRING_SIMPLE("name");
UnicodeString ver_attr = UNICODE_STRING_SIMPLE("version");
UnicodeString cksum_attr = UNICODE_STRING_SIMPLE("checksum");
const UXMLElement *testCase;
int32_t tc = 0;
while((testCase = root->nextChildElement(tc)) != NULL) {
if (testCase->getTagName().compare(test_case) == 0) {
char *id = getCString(testCase->getAttribute(id_attr));
char *script = getCString(testCase->getAttribute(script_attr));
char *lang = getCString(testCase->getAttribute(lang_attr));
char *fontName = NULL;
char *fontVer = NULL;
char *fontCksum = NULL;
const UXMLElement *element;
int32_t ec = 0;
int32_t charCount = 0;
int32_t typoFlags = 3; // kerning + ligatures...
UScriptCode scriptCode;
le_int32 languageCode = -1;
UnicodeString text, glyphs, indices, positions;
int32_t glyphCount = 0, indexCount = 0, positionCount = 0;
TestResult expected = {0, NULL, NULL, NULL};
uscript_getCode(script, &scriptCode, 1, &status);
if (LE_FAILURE(status)) {
log_err("invalid script name: %s.\n", script);
goto free_c_strings;
}
if (lang != NULL) {
languageCode = getLanguageCode(lang);
if (languageCode < 0) {
log_err("invalid language name: %s.\n", lang);
goto free_c_strings;
}
}
while((element = testCase->nextChildElement(ec)) != NULL) {
UnicodeString tag = element->getTagName();
// TODO: make sure that each element is only used once.
if (tag.compare(test_font) == 0) {
fontName = getCString(element->getAttribute(name_attr));
fontVer = getCString(element->getAttribute(ver_attr));
fontCksum = getCString(element->getAttribute(cksum_attr));
} else if (tag.compare(test_text) == 0) {
text = element->getText(TRUE);
charCount = text.length();
} else if (tag.compare(result_glyphs) == 0) {
glyphs = element->getText(TRUE);
} else if (tag.compare(result_indices) == 0) {
indices = element->getText(TRUE);
} else if (tag.compare(result_positions) == 0) {
positions = element->getText(TRUE);
} else {
// an unknown tag...
char *cTag = getCString(&tag);
log_info("Test %s: unknown element with tag \"%s\"\n", id, cTag);
freeCString(cTag);
}
}
expected.glyphs = (LEGlyphID *) getHexArray(glyphs, glyphCount);
expected.indices = (le_int32 *) getHexArray(indices, indexCount);
expected.positions = getFloatArray(positions, positionCount);
expected.glyphCount = glyphCount;
if (glyphCount < charCount || indexCount != glyphCount || positionCount < glyphCount * 2 + 2) {
log_err("Test %s: inconsistent input data: charCount = %d, glyphCount = %d, indexCount = %d, positionCount = %d\n",
id, charCount, glyphCount, indexCount, positionCount);
goto free_expected;
};
(*callback)(id, fontName, fontVer, fontCksum, scriptCode, languageCode, text.getBuffer(), charCount, &expected);
free_expected:
DELETE_ARRAY(expected.positions);
DELETE_ARRAY(expected.indices);
DELETE_ARRAY(expected.glyphs);
free_c_strings:
freeCString(fontCksum);
freeCString(fontVer);
freeCString(fontName);
freeCString(lang);
freeCString(script);
freeCString(id);
}
}
delete root;
delete parser;
#endif
}
U_CDECL_END

View File

@ -0,0 +1,25 @@
/*
*
* (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved
*
*/
#ifndef __XMLREADER_H
#define __XMLREADER_H
#include "LETypes.h"
#include "letest.h"
typedef void (*TestCaseCallback) (const char *testID,
const char *fontName,
const char *fontVersion,
const char *fontChecksum,
le_int32 scriptCode,
le_int32 languageCode,
const LEUnicode *text,
le_int32 charCount,
TestResult *expected);
U_CAPI void readTestFile(const char *testFilePath, TestCaseCallback callback);
#endif