mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-08 06:53:45 +00:00
ICU-1428 initial checkin of LayoutEngine sample
X-SVN-Rev: 6681
This commit is contained in:
parent
cd1ece982b
commit
3d90f8a272
37 changed files with 3840 additions and 4 deletions
4
icu4c/source/configure
vendored
4
icu4c/source/configure
vendored
|
@ -4174,7 +4174,7 @@ trap 'rm -fr `echo "README icudefs.mk \
|
|||
test/collperf/Makefile \
|
||||
test/thaitest/Makefile \
|
||||
test/letest/Makefile \
|
||||
samples/Makefile samples/date/Makefile samples/cal/Makefile \
|
||||
samples/Makefile samples/date/Makefile samples/cal/Makefile samples/layout/Makefile \
|
||||
common/unicode/platform.h common/icucfg.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
|
||||
EOF
|
||||
cat >> $CONFIG_STATUS <<EOF
|
||||
|
@ -4347,7 +4347,7 @@ CONFIG_FILES=\${CONFIG_FILES-"README icudefs.mk \
|
|||
test/collperf/Makefile \
|
||||
test/thaitest/Makefile \
|
||||
test/letest/Makefile \
|
||||
samples/Makefile samples/date/Makefile samples/cal/Makefile \
|
||||
samples/Makefile samples/date/Makefile samples/cal/Makefile samples/layout/Makefile \
|
||||
common/unicode/platform.h"}
|
||||
EOF
|
||||
cat >> $CONFIG_STATUS <<\EOF
|
||||
|
|
|
@ -4,7 +4,7 @@ dnl Copyright (c) 1999-2000, International Business Machines Corporation and
|
|||
dnl others. All Rights Reserved.
|
||||
dnl Stephen F. Booth, heavily modified by Yves and others
|
||||
|
||||
dnl $Id: configure.in,v 1.134 2001/11/01 17:28:18 grhoten-oss Exp $
|
||||
dnl $Id: configure.in,v 1.135 2001/11/07 23:48:17 emader-oss Exp $
|
||||
|
||||
dnl Process this file with autoconf to produce a configure script
|
||||
AC_INIT(common/unicode/utypes.h)
|
||||
|
@ -856,7 +856,7 @@ AC_OUTPUT([README icudefs.mk \
|
|||
test/collperf/Makefile \
|
||||
test/thaitest/Makefile \
|
||||
test/letest/Makefile \
|
||||
samples/Makefile samples/date/Makefile samples/cal/Makefile \
|
||||
samples/Makefile samples/date/Makefile samples/cal/Makefile samples/layout/Makefile \
|
||||
common/unicode/platform.h])
|
||||
|
||||
if test $ICU_USE_THREADS = 0; then
|
||||
|
|
8
icu4c/source/samples/layout/FontMap.GDI
Normal file
8
icu4c/source/samples/layout/FontMap.GDI
Normal file
|
@ -0,0 +1,8 @@
|
|||
# This is a sample FontMap file for Windows.
|
||||
# Fonts are specified by font name, as shown
|
||||
# in the "Fonts" folder.
|
||||
|
||||
LATIN: Times New Roman
|
||||
DEVANAGARI: Devanagari MT for IBM
|
||||
ARABIC: Times New Roman
|
||||
THAI: Thonburi
|
7
icu4c/source/samples/layout/FontMap.Gnome
Normal file
7
icu4c/source/samples/layout/FontMap.Gnome
Normal file
|
@ -0,0 +1,7 @@
|
|||
# This is a sample FontMap file for Linux.
|
||||
# Fonts are specified by file names.
|
||||
|
||||
LATIN: Times.TTF
|
||||
DEVANAGARI: Devamt.ttf
|
||||
ARABIC: Times.TTF
|
||||
THAI: THONBURI.TTF
|
206
icu4c/source/samples/layout/FontMap.cpp
Normal file
206
icu4c/source/samples/layout/FontMap.cpp
Normal file
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Copyright (C) 1998-2001, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#include "unicode/uscript.h"
|
||||
|
||||
#include "layout/LETypes.h"
|
||||
#include "layout/LEScripts.h"
|
||||
|
||||
#include "RenderingFontInstance.h"
|
||||
#include "GUISupport.h"
|
||||
#include "FontMap.h"
|
||||
|
||||
FontMap::FontMap(const char *fileName, le_int16 pointSize, GUISupport *guiSupport, RFIErrorCode &status)
|
||||
: fPointSize(pointSize), fFontCount(0), fGUISupport(guiSupport)
|
||||
{
|
||||
le_int32 i, script;
|
||||
|
||||
for (i = 0; i < scriptCodeCount; i += 1) {
|
||||
fFontIndices[i] = -1;
|
||||
fFontNames[i] = NULL;
|
||||
fFontInstances[i] = NULL;
|
||||
}
|
||||
|
||||
if (LE_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
char *c, *s, *line, buffer[BUFFER_SIZE];
|
||||
FILE *file;
|
||||
|
||||
file = fopen(fileName, "r");
|
||||
|
||||
if (file == NULL) {
|
||||
sprintf(errorMessage, "Could not open the font map file: %s.", fileName);
|
||||
fGUISupport->postErrorMessage(errorMessage, "Font Map Error");
|
||||
status = RFI_FONT_FILE_NOT_FOUND_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
while (fgets(buffer, BUFFER_SIZE, file) != NULL) {
|
||||
UScriptCode scriptCode;
|
||||
UErrorCode scriptStatus = U_ZERO_ERROR;
|
||||
|
||||
line = strip(buffer);
|
||||
if (line[0] == '#' || line[0] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
c = strchr(line, ':');
|
||||
c[0] = 0;
|
||||
s = strip(&c[1]);
|
||||
|
||||
uscript_getCode(strip(line), &scriptCode, 1, &scriptStatus);
|
||||
|
||||
if (U_FAILURE(scriptStatus) || scriptStatus == U_USING_FALLBACK_WARNING ||
|
||||
scriptStatus == U_USING_DEFAULT_WARNING) {
|
||||
sprintf(errorMessage, "The script name %s is invalid.", line);
|
||||
fGUISupport->postErrorMessage(errorMessage, "Font Map Error");
|
||||
status = RFI_ILLEGAL_ARGUMENT_ERROR;
|
||||
fclose(file);
|
||||
return;
|
||||
}
|
||||
|
||||
script = (le_int32) scriptCode;
|
||||
|
||||
if (fFontIndices[script] >= 0) {
|
||||
// FIXME: complain that this is a duplicate entry and bail (?)
|
||||
fFontIndices[script] = -1;
|
||||
}
|
||||
|
||||
fFontIndices[script] = getFontIndex(s);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
FontMap::~FontMap()
|
||||
{
|
||||
le_int32 font;
|
||||
|
||||
for (font = 0; font < fFontCount; font += 1) {
|
||||
if (fFontNames[font] != NULL) {
|
||||
delete[] (char *) fFontNames[font];
|
||||
}
|
||||
}
|
||||
|
||||
for (font = 0; font < fFontCount; font += 1) {
|
||||
if (fFontInstances[font] != NULL) {
|
||||
delete fFontInstances[font];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
le_int32 FontMap::getFontIndex(const char *fontName)
|
||||
{
|
||||
le_int32 index;
|
||||
|
||||
for (index = 0; index < fFontCount; index += 1) {
|
||||
if (strcmp(fontName, fFontNames[index]) == 0) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
if (fFontCount < (le_int32) scriptCodeCount) {
|
||||
index = fFontCount++;
|
||||
} else {
|
||||
// The font name table is full. Since there can
|
||||
// only be scriptCodeCount fonts in use at once,
|
||||
// there should be at least one that's not being
|
||||
// reference; find it and resue it's index.
|
||||
|
||||
for (index = 0; index < fFontCount; index += 1) {
|
||||
le_int32 script;
|
||||
|
||||
for (script = 0; script < scriptCodeCount; script += 1) {
|
||||
if (fFontIndices[script] == index) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (script >= scriptCodeCount) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (index >= scriptCodeCount) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
le_int32 len = strlen(fontName);
|
||||
char *s = new char[len + 1];
|
||||
|
||||
fFontNames[index] = strcpy(s, fontName);
|
||||
return index;
|
||||
}
|
||||
|
||||
char *FontMap::strip(char *s)
|
||||
{
|
||||
le_int32 start, end, len;
|
||||
|
||||
start = 0;
|
||||
len = strlen(s);
|
||||
|
||||
while (start < len && isspace(s[start])) {
|
||||
start += 1;
|
||||
}
|
||||
|
||||
end = len - 1;
|
||||
|
||||
while (end > start && isspace(s[end])) {
|
||||
end -= 1;
|
||||
}
|
||||
|
||||
if (end < len) {
|
||||
s[end + 1] = '\0';
|
||||
}
|
||||
|
||||
return &s[start];
|
||||
}
|
||||
|
||||
const RenderingFontInstance *FontMap::getScriptFont(le_int32 scriptCode, RFIErrorCode &status)
|
||||
{
|
||||
if (LE_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (scriptCode <= -1 || scriptCode >= scriptCodeCount) {
|
||||
status = RFI_ILLEGAL_ARGUMENT_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
le_int32 fontIndex = fFontIndices[scriptCode];
|
||||
|
||||
if (fontIndex < 0) {
|
||||
sprintf(errorMessage, "No font was set for script %s", uscript_getName((UScriptCode) scriptCode));
|
||||
fGUISupport->postErrorMessage(errorMessage, "Font Map Error");
|
||||
status = RFI_FONT_FILE_NOT_FOUND_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fFontInstances[fontIndex] == NULL) {
|
||||
fFontInstances[fontIndex] = openFont(fFontNames[fontIndex], fPointSize, status);
|
||||
|
||||
if (LE_FAILURE(status)) {
|
||||
sprintf(errorMessage, "Could not open font file %s", fFontNames[fontIndex]);
|
||||
fGUISupport->postErrorMessage(errorMessage, "Font Map Error");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return fFontInstances[fontIndex];
|
||||
}
|
||||
|
||||
|
||||
|
48
icu4c/source/samples/layout/FontMap.h
Normal file
48
icu4c/source/samples/layout/FontMap.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Copyright (C) 1998-2001, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __FONTMAP_H
|
||||
#define __FONTMAP_H
|
||||
|
||||
#include "layout/LETypes.h"
|
||||
#include "layout/LEScripts.h"
|
||||
|
||||
#include "RenderingFontInstance.h"
|
||||
#include "GUISupport.h"
|
||||
|
||||
#define BUFFER_SIZE 128
|
||||
|
||||
class FontMap
|
||||
{
|
||||
public:
|
||||
FontMap(const char *fileName, le_int16 pointSize, GUISupport *guiSupport, RFIErrorCode &status);
|
||||
|
||||
virtual ~FontMap();
|
||||
|
||||
virtual const RenderingFontInstance *getScriptFont(le_int32 scriptCode, RFIErrorCode &status);
|
||||
|
||||
protected:
|
||||
virtual const RenderingFontInstance *openFont(const char *fontName, le_int16 pointSize, RFIErrorCode &status) = 0;
|
||||
|
||||
char errorMessage[256];
|
||||
|
||||
private:
|
||||
static char *strip(char *s);
|
||||
le_int32 getFontIndex(const char *fontName);
|
||||
|
||||
le_int16 fPointSize;
|
||||
le_int32 fFontCount;
|
||||
|
||||
GUISupport *fGUISupport;
|
||||
|
||||
const RenderingFontInstance *fFontInstances[scriptCodeCount];
|
||||
const char *fFontNames[scriptCodeCount];
|
||||
le_int32 fFontIndices[scriptCodeCount];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
265
icu4c/source/samples/layout/GDIFontInstance.cpp
Normal file
265
icu4c/source/samples/layout/GDIFontInstance.cpp
Normal file
|
@ -0,0 +1,265 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
*******************************************************************************
|
||||
* file name: GDIFontInstance.cpp
|
||||
*
|
||||
* created on: 08/09/2000
|
||||
* created by: Eric R. Mader
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "layout/LETypes.h"
|
||||
#include "layout/LESwaps.h"
|
||||
|
||||
#include "RenderingFontInstance.h"
|
||||
#include "GDIFontInstance.h"
|
||||
#include "sfnt.h"
|
||||
#include "cmaps.h"
|
||||
|
||||
GDIFontInstance::GDIFontInstance(HDC hdc, TCHAR *faceName, le_int16 pointSize, RFIErrorCode &status)
|
||||
: fHdc(hdc), fFont(NULL), RenderingFontInstance(hdc, pointSize)
|
||||
{
|
||||
LOGFONT lf;
|
||||
FLOAT dpiX, dpiY;
|
||||
POINT pt;
|
||||
OUTLINETEXTMETRIC otm;
|
||||
|
||||
if (LE_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SaveDC(hdc);
|
||||
|
||||
SetGraphicsMode(hdc, GM_ADVANCED);
|
||||
ModifyWorldTransform(hdc, NULL, MWT_IDENTITY);
|
||||
SetViewportOrgEx(hdc, 0, 0, NULL);
|
||||
SetWindowOrgEx(hdc, 0, 0, NULL);
|
||||
|
||||
dpiX = (FLOAT) GetDeviceCaps(hdc, LOGPIXELSX);
|
||||
dpiY = (FLOAT) GetDeviceCaps(hdc, LOGPIXELSY);
|
||||
|
||||
#if 1
|
||||
pt.x = (int) (pointSize * dpiX / 72);
|
||||
pt.y = (int) (pointSize * dpiY / 72);
|
||||
|
||||
DPtoLP(hdc, &pt, 1);
|
||||
#else
|
||||
pt.x = pt.y = pointSize;
|
||||
#endif
|
||||
|
||||
lf.lfHeight = - pt.y;
|
||||
lf.lfWidth = 0;
|
||||
lf.lfEscapement = 0;
|
||||
lf.lfOrientation = 0;
|
||||
lf.lfWeight = 0;
|
||||
lf.lfItalic = 0;
|
||||
lf.lfUnderline = 0;
|
||||
lf.lfStrikeOut = 0;
|
||||
lf.lfCharSet = DEFAULT_CHARSET;
|
||||
lf.lfOutPrecision = 0;
|
||||
lf.lfClipPrecision = 0;
|
||||
lf.lfQuality = 0;
|
||||
lf.lfPitchAndFamily = 0;
|
||||
|
||||
lstrcpy(lf.lfFaceName, faceName);
|
||||
|
||||
fFont = CreateFontIndirect(&lf);
|
||||
|
||||
if (fFont == NULL) {
|
||||
status = RFI_FONT_FILE_NOT_FOUND_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
SelectObject(hdc, fFont);
|
||||
|
||||
UINT ret = GetOutlineTextMetrics(hdc, sizeof otm, &otm);
|
||||
|
||||
if (ret == 0) {
|
||||
status = RFI_MISSING_FONT_TABLE_ERROR;
|
||||
goto restore;
|
||||
}
|
||||
|
||||
fUnitsPerEM = otm.otmEMSquare;
|
||||
fAscent = otm.otmTextMetrics.tmAscent;
|
||||
fDescent = otm.otmTextMetrics.tmDescent;
|
||||
fLeading = otm.otmTextMetrics.tmExternalLeading;
|
||||
|
||||
status = initMapper();
|
||||
|
||||
if (LE_FAILURE(status)) {
|
||||
goto restore;
|
||||
}
|
||||
|
||||
status = initFontTableCache();
|
||||
|
||||
restore:
|
||||
RestoreDC(hdc, -1);
|
||||
}
|
||||
|
||||
GDIFontInstance::GDIFontInstance(HDC hdc, const char *faceName, le_int16 pointSize, RFIErrorCode &status)
|
||||
: fHdc(hdc), fFont(NULL), RenderingFontInstance(hdc, pointSize)
|
||||
{
|
||||
LOGFONTA lf;
|
||||
FLOAT dpiX, dpiY;
|
||||
POINT pt;
|
||||
OUTLINETEXTMETRIC otm;
|
||||
|
||||
if (LE_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SaveDC(hdc);
|
||||
|
||||
SetGraphicsMode(hdc, GM_ADVANCED);
|
||||
ModifyWorldTransform(hdc, NULL, MWT_IDENTITY);
|
||||
SetViewportOrgEx(hdc, 0, 0, NULL);
|
||||
SetWindowOrgEx(hdc, 0, 0, NULL);
|
||||
|
||||
dpiX = (FLOAT) GetDeviceCaps(hdc, LOGPIXELSX);
|
||||
dpiY = (FLOAT) GetDeviceCaps(hdc, LOGPIXELSY);
|
||||
|
||||
#if 1
|
||||
pt.x = (int) (pointSize * dpiX / 72);
|
||||
pt.y = (int) (pointSize * dpiY / 72);
|
||||
|
||||
DPtoLP(hdc, &pt, 1);
|
||||
#else
|
||||
pt.x = pt.y = pointSize;
|
||||
#endif
|
||||
|
||||
lf.lfHeight = - pt.y;
|
||||
lf.lfWidth = 0;
|
||||
lf.lfEscapement = 0;
|
||||
lf.lfOrientation = 0;
|
||||
lf.lfWeight = 0;
|
||||
lf.lfItalic = 0;
|
||||
lf.lfUnderline = 0;
|
||||
lf.lfStrikeOut = 0;
|
||||
lf.lfCharSet = DEFAULT_CHARSET;
|
||||
lf.lfOutPrecision = 0;
|
||||
lf.lfClipPrecision = 0;
|
||||
lf.lfQuality = 0;
|
||||
lf.lfPitchAndFamily = 0;
|
||||
|
||||
strcpy(lf.lfFaceName, faceName);
|
||||
|
||||
fFont = CreateFontIndirectA(&lf);
|
||||
|
||||
if (fFont == NULL) {
|
||||
status = RFI_FONT_FILE_NOT_FOUND_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
SelectObject(hdc, fFont);
|
||||
|
||||
UINT ret = GetOutlineTextMetrics(hdc, sizeof otm, &otm);
|
||||
|
||||
if (ret == 0) {
|
||||
status = RFI_MISSING_FONT_TABLE_ERROR;
|
||||
goto restore;
|
||||
}
|
||||
|
||||
fUnitsPerEM = otm.otmEMSquare;
|
||||
fAscent = otm.otmTextMetrics.tmAscent;
|
||||
fDescent = otm.otmTextMetrics.tmDescent;
|
||||
fLeading = otm.otmTextMetrics.tmExternalLeading;
|
||||
|
||||
status = initMapper();
|
||||
|
||||
if (LE_FAILURE(status)) {
|
||||
goto restore;
|
||||
}
|
||||
|
||||
status = initFontTableCache();
|
||||
|
||||
restore:
|
||||
RestoreDC(hdc, -1);
|
||||
}
|
||||
|
||||
GDIFontInstance::~GDIFontInstance()
|
||||
{
|
||||
#if 0
|
||||
flushFontTableCache();
|
||||
delete[] fTableCache;
|
||||
#endif
|
||||
|
||||
if (fFont != NULL) {
|
||||
// FIXME: call RemoveObject first?
|
||||
DeleteObject(fFont);
|
||||
}
|
||||
}
|
||||
|
||||
const void *GDIFontInstance::readFontTable(LETag tableTag) const
|
||||
{
|
||||
DWORD stag = SWAPL(tableTag);
|
||||
DWORD len = GetFontData(fHdc, stag, 0, NULL, 0);
|
||||
void *result = NULL;
|
||||
|
||||
if (len != GDI_ERROR) {
|
||||
result = new char[len];
|
||||
GetFontData(fHdc, stag, 0, result, len);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void GDIFontInstance::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const
|
||||
{
|
||||
advance.fX = 0;
|
||||
advance.fY = 0;
|
||||
|
||||
if (glyph == 0xFFFE || glyph == 0xFFFF) {
|
||||
return;
|
||||
}
|
||||
|
||||
GLYPHMETRICS metrics;
|
||||
DWORD result;
|
||||
MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
|
||||
|
||||
result = GetGlyphOutline(fHdc, glyph, GGO_GLYPH_INDEX | GGO_METRICS, &metrics, 0, NULL, &identity);
|
||||
|
||||
if (result == GDI_ERROR) {
|
||||
return;
|
||||
}
|
||||
|
||||
advance.fX = metrics.gmCellIncX;
|
||||
return;
|
||||
}
|
||||
|
||||
le_bool GDIFontInstance::getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point) const
|
||||
{
|
||||
#if 0
|
||||
hsFixedPoint2 pt;
|
||||
le_bool result;
|
||||
|
||||
result = fFontInstance->getGlyphPoint(glyph, pointNumber, pt);
|
||||
|
||||
if (result) {
|
||||
point.fX = xUnitsToPoints(pt.fX);
|
||||
point.fY = yUnitsToPoints(pt.fY);
|
||||
}
|
||||
|
||||
return result;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void GDIFontInstance::drawGlyphs(void *surface, LEGlyphID *glyphs, le_uint32 count, le_int32 *dx,
|
||||
le_int32 x, le_int32 y, le_int32 width, le_int32 height) const
|
||||
{
|
||||
HDC hdc = (HDC) surface;
|
||||
RECT clip;
|
||||
|
||||
clip.top = 0;
|
||||
clip.left = 0;
|
||||
clip.bottom = height;
|
||||
clip.right = width;
|
||||
|
||||
ExtTextOut(hdc, x, y - fAscent, ETO_CLIPPED | ETO_GLYPH_INDEX, &clip, glyphs, count, (INT *) dx);
|
||||
};
|
55
icu4c/source/samples/layout/GDIFontInstance.h
Normal file
55
icu4c/source/samples/layout/GDIFontInstance.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
|
||||
/*
|
||||
*******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
*******************************************************************************
|
||||
* file name: GDIFontInstance.h
|
||||
*
|
||||
* created on: 08/09/2000
|
||||
* created by: Eric R. Mader
|
||||
*/
|
||||
|
||||
#ifndef __GDIFONTINSTANCE_H
|
||||
#define __GDIFONTINSTANCE_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "layout/LETypes.h"
|
||||
#include "RenderingFontInstance.h"
|
||||
#include "cmaps.h"
|
||||
|
||||
class GDIFontInstance : public RenderingFontInstance
|
||||
{
|
||||
protected:
|
||||
HDC fHdc;
|
||||
HFONT fFont;
|
||||
|
||||
virtual const void *readFontTable(LETag tableTag) const;
|
||||
|
||||
public:
|
||||
GDIFontInstance(HDC theHDC, TCHAR *faceName, le_int16 pointSize, RFIErrorCode &status);
|
||||
GDIFontInstance(HDC theHDC, const char *faceName, le_int16 pointSize, RFIErrorCode &status);
|
||||
//GDIFontInstance(HDC theHDC, le_int16 pointSize);
|
||||
|
||||
virtual ~GDIFontInstance();
|
||||
|
||||
virtual void getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const;
|
||||
|
||||
virtual le_bool getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point) const;
|
||||
|
||||
virtual const void setFont(void *surface) const
|
||||
{
|
||||
HDC hdc = (HDC) surface;
|
||||
|
||||
SelectObject(hdc, fFont);
|
||||
};
|
||||
|
||||
virtual void drawGlyphs(void *surface, LEGlyphID *glyphs, le_uint32 count, le_int32 *dx,
|
||||
le_int32 x, le_int32 y, le_int32 width, le_int32 height) const;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
31
icu4c/source/samples/layout/GDIFontMap.cpp
Normal file
31
icu4c/source/samples/layout/GDIFontMap.cpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Copyright (C) 1998-2001, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "RenderingFontInstance.h"
|
||||
#include "GDIFontInstance.h"
|
||||
|
||||
#include "GUISupport.h"
|
||||
#include "FontMap.h"
|
||||
#include "GDIFontMap.h"
|
||||
|
||||
GDIFontMap::GDIFontMap(HDC hdc, const char *fileName, le_int16 pointSize, GUISupport *guiSupport, RFIErrorCode &status)
|
||||
: FontMap(fileName, pointSize, guiSupport, status), fHdc(hdc)
|
||||
{
|
||||
// nothing to do?
|
||||
}
|
||||
|
||||
GDIFontMap::~GDIFontMap()
|
||||
{
|
||||
// anything?
|
||||
}
|
||||
|
||||
const RenderingFontInstance *GDIFontMap::openFont(const char *fontName, le_int16 pointSize, RFIErrorCode &status)
|
||||
{
|
||||
return new GDIFontInstance(fHdc, fontName, pointSize, status);
|
||||
}
|
37
icu4c/source/samples/layout/GDIFontMap.h
Normal file
37
icu4c/source/samples/layout/GDIFontMap.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Copyright (C) 1998-2001, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __GDIFONTMAP_H
|
||||
#define __GDIFONTMAP_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "unicode/uscript.h"
|
||||
|
||||
#include "layout/LETypes.h"
|
||||
|
||||
#include "FontMap.h"
|
||||
#include "GUISupport.h"
|
||||
#include "RenderingFontInstance.h"
|
||||
|
||||
#define BUFFER_SIZE 128
|
||||
|
||||
class GDIFontMap : public FontMap
|
||||
{
|
||||
public:
|
||||
GDIFontMap(HDC hdc, const char *fileName, le_int16 pointSize, GUISupport *guiSupport, RFIErrorCode &status);
|
||||
|
||||
virtual ~GDIFontMap();
|
||||
|
||||
protected:
|
||||
virtual const RenderingFontInstance *openFont(const char *fontName, le_int16 pointSize, RFIErrorCode &status);
|
||||
|
||||
private:
|
||||
HDC fHdc;
|
||||
};
|
||||
|
||||
#endif
|
22
icu4c/source/samples/layout/GDIGUISupport.cpp
Normal file
22
icu4c/source/samples/layout/GDIGUISupport.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
*******************************************************************************
|
||||
* file name: GDIGUISupport.h
|
||||
*
|
||||
* created on: 11/06/2001
|
||||
* created by: Eric R. Mader
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "GDIGUISupport.h"
|
||||
|
||||
void GDIGUISupport::postErrorMessage(const char *message, const char *title)
|
||||
{
|
||||
MessageBoxA(NULL, message, title, MB_ICONERROR);
|
||||
}
|
||||
|
28
icu4c/source/samples/layout/GDIGUISupport.h
Normal file
28
icu4c/source/samples/layout/GDIGUISupport.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
*******************************************************************************
|
||||
* file name: GDIGUISupport.h
|
||||
*
|
||||
* created on: 11/06/2001
|
||||
* created by: Eric R. Mader
|
||||
*/
|
||||
|
||||
#ifndef __GDIGUISUPPORT_H
|
||||
#define __GDIGUISUPPORT_H
|
||||
|
||||
#include "GUISupport.h"
|
||||
|
||||
class GDIGUISupport : public GUISupport
|
||||
{
|
||||
public:
|
||||
GDIGUISupport() {};
|
||||
~GDIGUISupport() {};
|
||||
|
||||
virtual void postErrorMessage(const char *message, const char *title);
|
||||
};
|
||||
|
||||
#endif
|
26
icu4c/source/samples/layout/GUISupport.h
Normal file
26
icu4c/source/samples/layout/GUISupport.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
*******************************************************************************
|
||||
* file name: GUISupport.h
|
||||
*
|
||||
* created on: 11/06/2001
|
||||
* created by: Eric R. Mader
|
||||
*/
|
||||
|
||||
#ifndef __GUISUPPORT_H
|
||||
#define __GUISUPPORT_H
|
||||
|
||||
class GUISupport
|
||||
{
|
||||
public:
|
||||
GUISupport() {};
|
||||
~GUISupport() {};
|
||||
|
||||
virtual void postErrorMessage(const char *message, const char *title) = 0;
|
||||
};
|
||||
|
||||
#endif
|
276
icu4c/source/samples/layout/GnomeFontInstance.cpp
Normal file
276
icu4c/source/samples/layout/GnomeFontInstance.cpp
Normal file
|
@ -0,0 +1,276 @@
|
|||
|
||||
/*
|
||||
*******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
*******************************************************************************
|
||||
* file name: GnomeFontInstance.cpp
|
||||
*
|
||||
* created on: 08/30/2001
|
||||
* created by: Eric R. Mader
|
||||
*/
|
||||
|
||||
#include <gnome.h>
|
||||
#include "freetype/freetype.h"
|
||||
|
||||
#include "layout/LETypes.h"
|
||||
#include "layout/LESwaps.h"
|
||||
|
||||
#include "GnomeFontInstance.h"
|
||||
#include "sfnt.h"
|
||||
#include "cmaps.h"
|
||||
|
||||
GnomeFontInstance::GnomeFontInstance(TT_Engine engine, const TT_Text *fontPathName, le_int16 pointSize, RFIErrorCode &status)
|
||||
: RenderingFontInstance(NULL, pointSize)
|
||||
{
|
||||
TT_Error error;
|
||||
TT_Face_Properties faceProperties;
|
||||
|
||||
fFace.z = NULL;
|
||||
|
||||
error = TT_Open_Face(engine, fontPathName, &fFace);
|
||||
|
||||
if (error != 0) {
|
||||
status = RFI_FONT_FILE_NOT_FOUND_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
error = TT_New_Instance(fFace, &fInstance);
|
||||
|
||||
if (error != 0) {
|
||||
status = RFI_OUT_OF_MEMORY_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: what about the display resolution?
|
||||
// TT_Set_Instance_Resolutions(fInstance, 72, 72);
|
||||
TT_Set_Instance_CharSize(fInstance, pointSize << 6);
|
||||
|
||||
TT_Get_Face_Properties(fFace, &faceProperties);
|
||||
|
||||
fUnitsPerEM = faceProperties.header->Units_Per_EM;
|
||||
|
||||
fAscent = (le_int32) yUnitsToPoints(faceProperties.horizontal->Ascender);
|
||||
fDescent = (le_int32) -yUnitsToPoints(faceProperties.horizontal->Descender);
|
||||
fLeading = (le_int32) yUnitsToPoints(faceProperties.horizontal->Line_Gap);
|
||||
|
||||
// printf("Face = %s, unitsPerEM = %d, ascent = %d, descent = %d\n", fontPathName, fUnitsPerEM, fAscent, fDescent);
|
||||
|
||||
error = TT_New_Glyph(fFace, &fGlyph);
|
||||
|
||||
if (error != 0) {
|
||||
status = RFI_OUT_OF_MEMORY_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
status = initMapper();
|
||||
if (LE_SUCCESS(status)) {
|
||||
status = initFontTableCache();
|
||||
}
|
||||
}
|
||||
|
||||
GnomeFontInstance::~GnomeFontInstance()
|
||||
{
|
||||
if (fFace.z != NULL) {
|
||||
TT_Close_Face(fFace);
|
||||
}
|
||||
}
|
||||
|
||||
const void *GnomeFontInstance::readFontTable(LETag tableTag) const
|
||||
{
|
||||
TT_Long len = 0;
|
||||
void *result = NULL;
|
||||
|
||||
TT_Get_Font_Data(fFace, tableTag, 0, NULL, &len);
|
||||
|
||||
if (len > 0) {
|
||||
result = new char[len];
|
||||
TT_Get_Font_Data(fFace, tableTag, 0, result, &len);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void GnomeFontInstance::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const
|
||||
{
|
||||
advance.fX = 0;
|
||||
advance.fY = 0;
|
||||
|
||||
if (glyph == 0xFFFF) {
|
||||
return;
|
||||
}
|
||||
|
||||
TT_Glyph_Metrics metrics;
|
||||
TT_Error error;
|
||||
|
||||
error = TT_Load_Glyph(fInstance, fGlyph, glyph, TTLOAD_SCALE_GLYPH | TTLOAD_HINT_GLYPH);
|
||||
|
||||
if (error != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
TT_Get_Glyph_Metrics(fGlyph, &metrics);
|
||||
|
||||
advance.fX = metrics.advance >> 6;
|
||||
return;
|
||||
}
|
||||
|
||||
le_bool GnomeFontInstance::getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point) const
|
||||
{
|
||||
#if 1
|
||||
TT_Outline outline;
|
||||
TT_Error error;
|
||||
|
||||
error = TT_Load_Glyph(fInstance, fGlyph, glyph, TTLOAD_SCALE_GLYPH | TTLOAD_HINT_GLYPH);
|
||||
|
||||
if (error != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
error = TT_Get_Glyph_Outline(fGlyph, &outline);
|
||||
|
||||
if (error != 0 || pointNumber >= outline.n_points) {
|
||||
return false;
|
||||
}
|
||||
|
||||
point.fX = outline.points[pointNumber].x >> 6;
|
||||
point.fY = outline.points[pointNumber].y >> 6;
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define _R(b7,b6,b5,b4,b3,b2,b1,b0) ((b0<<7)|(b1<<6)|(b2<<5)|(b3<<4)|(b4<<3)|(b5<<2)|(b6<<1)|b7)
|
||||
#define _B(b,n) ((b>>n)&1)
|
||||
#define _H(b) _R(_B(b,7),_B(b,6),_B(b,5),_B(b,4),_B(b,3),_B(b,2),_B(b,1),_B(b,0))
|
||||
|
||||
const char bitReverse[256] = {
|
||||
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
|
||||
0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
|
||||
0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
|
||||
0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
|
||||
0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
|
||||
0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
|
||||
0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
|
||||
0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
|
||||
0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
|
||||
0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
|
||||
0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
|
||||
0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
|
||||
0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
|
||||
0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
|
||||
0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
|
||||
0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
|
||||
};
|
||||
|
||||
|
||||
// FIXME: this would be much faster if we cached the TT_Glyph objects based on the glyph ID...
|
||||
void GnomeFontInstance::drawGlyphs(void *surface, LEGlyphID *glyphs, le_uint32 count, le_int32 *dx,
|
||||
le_int32 x, le_int32 y, le_int32 width, le_int32 height) const
|
||||
{
|
||||
GtkWidget *widget = (GtkWidget *) surface;
|
||||
le_int32 i, xx = 0, yy = 0, zz;
|
||||
le_int32 minx = 0, maxx = 0, miny = 0, maxy = 0;
|
||||
TT_Glyph_Metrics metrics;
|
||||
TT_Error error;
|
||||
|
||||
//printf("drawGlyphs() - x = %d, y = %d, ", x, y);
|
||||
|
||||
for (i = 0; i < count; i += 1) {
|
||||
error = TT_Load_Glyph(fInstance, fGlyph, glyphs[i], TTLOAD_SCALE_GLYPH | TTLOAD_HINT_GLYPH);
|
||||
if (error == 0) {
|
||||
TT_Get_Glyph_Metrics(fGlyph, &metrics);
|
||||
|
||||
zz = xx + metrics.bbox.xMin;
|
||||
if (minx > zz) {
|
||||
minx = zz;
|
||||
}
|
||||
|
||||
zz = xx + metrics.bbox.xMax;
|
||||
if (maxx < zz) {
|
||||
maxx = zz;
|
||||
}
|
||||
|
||||
zz = yy + metrics.bbox.yMin;
|
||||
if (miny > zz) {
|
||||
miny = zz;
|
||||
}
|
||||
|
||||
zz = yy + metrics.bbox.yMax;
|
||||
if (maxy < zz) {
|
||||
maxy = zz;
|
||||
}
|
||||
}
|
||||
|
||||
xx += (dx[i] * 64);
|
||||
}
|
||||
|
||||
|
||||
minx = (minx & -64) >> 6;
|
||||
miny = (miny & -64) >> 6;
|
||||
|
||||
maxx = ((maxx + 63) & -64) >> 6;
|
||||
maxy = ((maxy + 63) & -64) >> 6;
|
||||
|
||||
//printf("minx = %d, maxx = %d, miny = %d, maxy = %d\n", minx, maxx, miny, maxy);
|
||||
|
||||
TT_Raster_Map raster;
|
||||
unsigned char *bits;
|
||||
|
||||
raster.flow = TT_Flow_Down;
|
||||
raster.width = maxx - minx;
|
||||
raster.rows = maxy - miny;
|
||||
raster.cols = (raster.width + 7) / 8;
|
||||
raster.size = raster.cols * raster.rows;
|
||||
|
||||
raster.bitmap = bits = new unsigned char[raster.size];
|
||||
|
||||
for (i = 0; i < raster.size; i += 1) {
|
||||
bits[i] = 0;
|
||||
}
|
||||
|
||||
xx = (-minx) * 64; yy = (-miny) * 64;
|
||||
|
||||
for (i = 0; i < count; i += 1) {
|
||||
if (glyphs[i] < 0xFFFE) {
|
||||
error = TT_Load_Glyph(fInstance, fGlyph, glyphs[i], TTLOAD_SCALE_GLYPH | TTLOAD_HINT_GLYPH);
|
||||
|
||||
if (error == 0) {
|
||||
TT_Get_Glyph_Bitmap(fGlyph, &raster, xx, yy);
|
||||
}
|
||||
}
|
||||
|
||||
xx += (dx[i] * 64);
|
||||
}
|
||||
|
||||
for (i = 0; i < raster.size; i += 1) {
|
||||
bits[i] = bitReverse[bits[i]];
|
||||
}
|
||||
|
||||
if (raster.width > 0 && raster.rows > 0) {
|
||||
GdkBitmap *bitmap = gdk_bitmap_create_from_data(NULL, (const gchar *) raster.bitmap, raster.width, raster.rows);
|
||||
|
||||
gint bitsx = x + minx;
|
||||
gint bitsy = y - maxy;
|
||||
|
||||
gdk_gc_set_clip_origin(widget->style->black_gc, bitsx, bitsy);
|
||||
gdk_gc_set_clip_mask(widget->style->black_gc, bitmap);
|
||||
|
||||
gdk_draw_rectangle(widget->window,
|
||||
widget->style->black_gc,
|
||||
TRUE,
|
||||
bitsx, bitsy,
|
||||
raster.width, raster.rows);
|
||||
|
||||
gdk_gc_set_clip_origin(widget->style->black_gc, 0, 0);
|
||||
gdk_gc_set_clip_mask(widget->style->black_gc, NULL);
|
||||
|
||||
gdk_bitmap_unref(bitmap);
|
||||
}
|
||||
|
||||
delete[] bits;
|
||||
}
|
49
icu4c/source/samples/layout/GnomeFontInstance.h
Normal file
49
icu4c/source/samples/layout/GnomeFontInstance.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
|
||||
/*
|
||||
*******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
*******************************************************************************
|
||||
* file name: GnomeFontInstance.h
|
||||
*
|
||||
* created on: 08/30/2001
|
||||
* created by: Eric R. Mader
|
||||
*/
|
||||
|
||||
#ifndef __GNOMEFONTINSTANCE_H
|
||||
#define __GNOMEFONTINSTANCE_H
|
||||
|
||||
#include <gnome.h>
|
||||
#include "freetype/freetype.h"
|
||||
|
||||
#include "layout/LETypes.h"
|
||||
#include "RenderingFontInstance.h"
|
||||
#include "cmaps.h"
|
||||
|
||||
class GnomeFontInstance : public RenderingFontInstance
|
||||
{
|
||||
protected:
|
||||
TT_Face fFace;
|
||||
TT_Instance fInstance;
|
||||
TT_Glyph fGlyph;
|
||||
|
||||
virtual const void *readFontTable(LETag tableTag) const;
|
||||
|
||||
public:
|
||||
GnomeFontInstance(TT_Engine engine, const TT_Text *fontPathName, le_int16 pointSize, RFIErrorCode &status);
|
||||
|
||||
virtual ~GnomeFontInstance();
|
||||
|
||||
|
||||
virtual void getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const;
|
||||
|
||||
virtual le_bool getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point) const;
|
||||
|
||||
virtual void drawGlyphs(void *surface, LEGlyphID *glyphs, le_uint32 count, le_int32 *dx,
|
||||
le_int32 x, le_int32 y, le_int32 width, le_int32 height) const;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
33
icu4c/source/samples/layout/GnomeFontMap.cpp
Normal file
33
icu4c/source/samples/layout/GnomeFontMap.cpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Copyright (C) 1998-2001, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "freetype/freetype.h"
|
||||
|
||||
#include "RenderingFontInstance.h"
|
||||
#include "GnomeFontInstance.h"
|
||||
|
||||
#include "GUISupport.h"
|
||||
#include "FontMap.h"
|
||||
#include "GnomeFontMap.h"
|
||||
|
||||
GnomeFontMap::GnomeFontMap(TT_Engine engine, const char *fileName, le_int16 pointSize, GUISupport *guiSupport, RFIErrorCode &status)
|
||||
: FontMap(fileName, pointSize, guiSupport, status), fEngine(engine)
|
||||
{
|
||||
// nothing to do?
|
||||
}
|
||||
|
||||
GnomeFontMap::~GnomeFontMap()
|
||||
{
|
||||
// anything?
|
||||
}
|
||||
|
||||
const RenderingFontInstance *GnomeFontMap::openFont(const char *fontName, le_int16 pointSize, RFIErrorCode &status)
|
||||
{
|
||||
return new GnomeFontInstance(fEngine, fontName, pointSize, status);
|
||||
}
|
37
icu4c/source/samples/layout/GnomeFontMap.h
Normal file
37
icu4c/source/samples/layout/GnomeFontMap.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Copyright (C) 1998-2001, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __GNOMEFONTMAP_H
|
||||
#define __GNOMEFONTMAP_H
|
||||
|
||||
#include "freetype/freetype.h"
|
||||
|
||||
#include "unicode/uscript.h"
|
||||
|
||||
#include "layout/LETypes.h"
|
||||
|
||||
#include "GUISupport.h"
|
||||
#include "FontMap.h"
|
||||
#include "RenderingFontInstance.h"
|
||||
|
||||
#define BUFFER_SIZE 128
|
||||
|
||||
class GnomeFontMap : public FontMap
|
||||
{
|
||||
public:
|
||||
GnomeFontMap(TT_Engine engine, const char *fileName, le_int16 pointSize, GUISupport *guiSupport, RFIErrorCode &status);
|
||||
|
||||
virtual ~GnomeFontMap();
|
||||
|
||||
protected:
|
||||
virtual const RenderingFontInstance *openFont(const char *fontName, le_int16 pointSize, RFIErrorCode &status);
|
||||
|
||||
private:
|
||||
TT_Engine fEngine;
|
||||
};
|
||||
|
||||
#endif
|
23
icu4c/source/samples/layout/GnomeGUISupport.cpp
Normal file
23
icu4c/source/samples/layout/GnomeGUISupport.cpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
*******************************************************************************
|
||||
* file name: GnomeGUISupport.h
|
||||
*
|
||||
* created on: 11/06/2001
|
||||
* created by: Eric R. Mader
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "GnomeGUISupport.h"
|
||||
|
||||
void GnomeGUISupport::postErrorMessage(const char *message, const char *title)
|
||||
{
|
||||
fprintf(stderr, "%s: %s\n", title, message);
|
||||
}
|
||||
|
||||
|
28
icu4c/source/samples/layout/GnomeGUISupport.h
Normal file
28
icu4c/source/samples/layout/GnomeGUISupport.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
*******************************************************************************
|
||||
* file name: GnomeGUISupport.h
|
||||
*
|
||||
* created on: 11/06/2001
|
||||
* created by: Eric R. Mader
|
||||
*/
|
||||
|
||||
#ifndef __GNOMEGUISUPPORT_H
|
||||
#define __GNOMEGUISUPPORT_H
|
||||
|
||||
#include "GUISupport.h"
|
||||
|
||||
class GnomeGUISupport : public GUISupport
|
||||
{
|
||||
public:
|
||||
GnomeGUISupport() {};
|
||||
~GnomeGUISupport() {};
|
||||
|
||||
virtual void postErrorMessage(const char *message, const char *title);
|
||||
};
|
||||
|
||||
#endif
|
88
icu4c/source/samples/layout/Makefile.in
Normal file
88
icu4c/source/samples/layout/Makefile.in
Normal file
|
@ -0,0 +1,88 @@
|
|||
## Makefile.in for ICU - samples/layout
|
||||
## Copyright (c) 2001, International Business Machines Corporation and
|
||||
## others. All Rights Reserved.
|
||||
|
||||
## Source directory information
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
top_builddir = ../..
|
||||
|
||||
include $(top_builddir)/icudefs.mk
|
||||
|
||||
## Platform-specific setup
|
||||
include @platform_make_fragment@
|
||||
|
||||
## Build directory information
|
||||
subdir = samples/layout
|
||||
|
||||
## Extra files to remove for 'make clean'
|
||||
CLEANFILES = *~ $(DEPS)
|
||||
|
||||
## Target information
|
||||
TARGET = gnomelayout
|
||||
|
||||
DEFS = @DEFS@
|
||||
CPPFLAGS = @CPPFLAGS@ `gnome-config --cflags gnomeui` -I$(top_builddir)/common -I$(top_srcdir)/common -I$(top_srcdir)/i18n -I$(top_srcdir)/layout -I$(top_srcdir)
|
||||
CFLAGS = @CFLAGS@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
ENABLE_RPATH = @ENABLE_RPATH@
|
||||
ifeq ($(ENABLE_RPATH),YES)
|
||||
RPATHLDFLAGS = $(LD_RPATH)$(LD_RPATH_PRE)$(libdir)
|
||||
endif
|
||||
LDFLAGS = @LDFLAGS@ $(RPATHLDFLAGS)
|
||||
INVOKE = $(LDLIBRARYPATH_ENVVAR)=$(top_builddir)/common:$(top_builddir)/i18n:$(top_builddir)/tools/toolutil:$$$(LDLIBRARYPATH_ENVVAR)
|
||||
LIBS = $(LIBICULE) $(LIBICUUC) $(LIBICUI18N) @LIBS@ @LIB_M@ `gnome-config --libs gnomeui` -lttf
|
||||
|
||||
|
||||
OBJECTS=cmaps.o scrptrun.o UnicodeReader.o GnomeGUISupport.o FontMap.o GnomeFontMap.o RenderingFontInstance.o GnomeFontInstance.o paragraph.o gnomelayout.o
|
||||
|
||||
DEPS = $(OBJECTS:.o=.d)
|
||||
|
||||
## List of phony targets
|
||||
.PHONY : all all-local install install-local clean clean-local \
|
||||
distclean distclean-local dist dist-local check check-local
|
||||
|
||||
## Clear suffix list
|
||||
.SUFFIXES :
|
||||
|
||||
## List of standard targets
|
||||
all: all-local
|
||||
install: install-local
|
||||
clean: clean-local
|
||||
distclean : distclean-local
|
||||
dist: dist-local
|
||||
check: all check-local
|
||||
|
||||
all-local: $(TARGET)
|
||||
|
||||
install-local:
|
||||
|
||||
dist-local:
|
||||
|
||||
clean-local:
|
||||
test -z "$(CLEANFILES)" || $(RMV) $(CLEANFILES)
|
||||
$(RMV) $(OBJECTS) $(TARGET)
|
||||
|
||||
distclean-local: clean-local
|
||||
$(RMV) Makefile
|
||||
|
||||
check-local: all-local
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
$(TARGET) : $(OBJECTS)
|
||||
$(LINK.cc) -o $@ $^ $(LIBS)
|
||||
|
||||
invoke:
|
||||
ICU_DATA=$${ICU_DATA:-$(top_builddir)/data/} TZ=PST8PDT $(INVOKE) $(INVOCATION)
|
||||
|
||||
ifeq (,$(MAKECMDGOALS))
|
||||
-include $(DEPS)
|
||||
else
|
||||
ifneq ($(patsubst %clean,,$(MAKECMDGOALS)),)
|
||||
-include $(DEPS)
|
||||
endif
|
||||
endif
|
164
icu4c/source/samples/layout/RenderingFontInstance.cpp
Normal file
164
icu4c/source/samples/layout/RenderingFontInstance.cpp
Normal file
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
*******************************************************************************
|
||||
* file name: RenderingFontInstance.cpp
|
||||
*
|
||||
* created on: 10/22/2001
|
||||
* created by: Eric R. Mader
|
||||
*/
|
||||
|
||||
#include "LETypes.h"
|
||||
#include "LEFontInstance.h"
|
||||
#include "RenderingFontInstance.h"
|
||||
#include "LESwaps.h"
|
||||
#include "sfnt.h"
|
||||
#include "cmaps.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
RenderingFontInstance::RenderingFontInstance(void *surface, le_int16 pointSize)
|
||||
: fSurface(surface), fPointSize(pointSize), fUnitsPerEM(0), fAscent(0), fDescent(), fLeading(0),
|
||||
fTableCache(NULL), fTableCacheCurr(0), fTableCacheSize(0), fMapper(NULL)
|
||||
{
|
||||
// we expect the subclass to call
|
||||
// initMapper() and initFontTableCache
|
||||
}
|
||||
|
||||
RenderingFontInstance::~RenderingFontInstance()
|
||||
{
|
||||
flushFontTableCache();
|
||||
delete[] fTableCache;
|
||||
|
||||
delete fMapper;
|
||||
}
|
||||
|
||||
void RenderingFontInstance::mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count,
|
||||
le_bool reverse, const LECharMapper *mapper, LEGlyphID glyphs[]) const
|
||||
{
|
||||
le_int32 i, out = 0, dir = 1;
|
||||
|
||||
if (reverse) {
|
||||
out = count - 1;
|
||||
dir = -1;
|
||||
}
|
||||
|
||||
for (i = offset; i < offset + count; i += 1, out += dir) {
|
||||
LEUnicode16 high = chars[i];
|
||||
LEUnicode32 code = high;
|
||||
|
||||
if (i < offset + count - 1 && high >= 0xD800 && high <= 0xDBFF) {
|
||||
LEUnicode16 low = chars[i + 1];
|
||||
|
||||
if (low >= 0xDC00 && low <= 0xDFFF) {
|
||||
code = (high - 0xD800) * 0x400 + low - 0xDC00 + 0x10000;
|
||||
}
|
||||
}
|
||||
|
||||
glyphs[out] = mapCharToGlyph(code, mapper);
|
||||
|
||||
if (code >= 0x10000) {
|
||||
i += 1;
|
||||
glyphs[out += dir] = 0xFFFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LEGlyphID RenderingFontInstance::mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper) const
|
||||
{
|
||||
LEUnicode32 mappedChar = mapper->mapChar(ch);
|
||||
|
||||
if (mappedChar == 0xFFFE || mappedChar == 0xFFFF) {
|
||||
return 0xFFFF;
|
||||
}
|
||||
|
||||
if (mappedChar == 0x200C || mappedChar == 0x200D) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return fMapper->unicodeToGlyph(mappedChar);
|
||||
}
|
||||
|
||||
const void *RenderingFontInstance::getFontTable(LETag tableTag) const
|
||||
{
|
||||
for (int i = 0; i < fTableCacheCurr; i += 1) {
|
||||
if (fTableCache[i].tag == tableTag) {
|
||||
return fTableCache[i].table;
|
||||
}
|
||||
}
|
||||
|
||||
RenderingFontInstance *realThis = (RenderingFontInstance *) this;
|
||||
|
||||
if (realThis->fTableCacheCurr >= realThis->fTableCacheSize) {
|
||||
le_int32 newSize = realThis->fTableCacheSize + TABLE_CACHE_GROW;
|
||||
TableCacheEntry *newTable = new TableCacheEntry[newSize];
|
||||
|
||||
// FIXME: need a better strategy than this...
|
||||
if (newTable == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(newTable, realThis->fTableCache, realThis->fTableCacheSize * sizeof realThis->fTableCache[0]);
|
||||
delete[] realThis->fTableCache;
|
||||
|
||||
for (int i = realThis->fTableCacheSize; i < newSize; i += 1) {
|
||||
newTable[i].tag = 0;
|
||||
newTable[i].table = NULL;
|
||||
}
|
||||
|
||||
realThis->fTableCache = newTable;
|
||||
realThis->fTableCacheSize = newSize;
|
||||
}
|
||||
|
||||
realThis->fTableCache[realThis->fTableCacheCurr].tag = tableTag;
|
||||
realThis->fTableCache[realThis->fTableCacheCurr].table = (void *) realThis->readFontTable(tableTag);
|
||||
|
||||
return fTableCache[realThis->fTableCacheCurr++].table;
|
||||
};
|
||||
|
||||
RFIErrorCode RenderingFontInstance::initMapper()
|
||||
{
|
||||
LETag cmapTag = 0x636D6170; // 'cmap'
|
||||
const CMAPTable *cmap = (const CMAPTable *) readFontTable(cmapTag);
|
||||
|
||||
if (cmap == NULL) {
|
||||
return RFI_MISSING_FONT_TABLE_ERROR;
|
||||
}
|
||||
|
||||
fMapper = CMAPMapper::createUnicodeMapper(cmap);
|
||||
|
||||
if (fMapper == NULL) {
|
||||
return RFI_MISSING_FONT_TABLE_ERROR;
|
||||
}
|
||||
|
||||
return RFI_NO_ERROR;
|
||||
}
|
||||
|
||||
RFIErrorCode RenderingFontInstance::initFontTableCache()
|
||||
{
|
||||
fTableCacheSize = TABLE_CACHE_INIT;
|
||||
fTableCache = new TableCacheEntry[fTableCacheSize];
|
||||
|
||||
if (fTableCache == 0) {
|
||||
return RFI_OUT_OF_MEMORY_ERROR;
|
||||
}
|
||||
|
||||
for (int i = 0; i < fTableCacheSize; i += 1) {
|
||||
fTableCache[i].tag = 0;
|
||||
fTableCache[i].table = NULL;
|
||||
}
|
||||
|
||||
return RFI_NO_ERROR;
|
||||
}
|
||||
|
||||
void RenderingFontInstance::flushFontTableCache()
|
||||
{
|
||||
for (int i = fTableCacheCurr - 1; i >= 0; i -= 1) {
|
||||
delete[] (char *) fTableCache[i].table;
|
||||
}
|
||||
|
||||
fTableCacheCurr = 0;
|
||||
}
|
175
icu4c/source/samples/layout/RenderingFontInstance.h
Normal file
175
icu4c/source/samples/layout/RenderingFontInstance.h
Normal file
|
@ -0,0 +1,175 @@
|
|||
|
||||
/*
|
||||
*******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
*******************************************************************************
|
||||
* file name: RenderingFontInstance.h
|
||||
*
|
||||
* created on: 10/23/2001
|
||||
* created by: Eric R. Mader
|
||||
*/
|
||||
|
||||
#ifndef __RENDERINGFONTINSTANCE_H
|
||||
#define __RENDERINGFONTINSTANCE_H
|
||||
|
||||
#include "LETypes.h"
|
||||
#include "LEFontInstance.h"
|
||||
#include "cmaps.h"
|
||||
|
||||
#define TABLE_CACHE_INIT 5
|
||||
#define TABLE_CACHE_GROW 5
|
||||
|
||||
struct TableCacheEntry
|
||||
{
|
||||
LETag tag;
|
||||
void *table;
|
||||
};
|
||||
|
||||
enum RFIErrorCode {
|
||||
RFI_NO_ERROR = 0,
|
||||
|
||||
RFI_ILLEGAL_ARGUMENT_ERROR = 1,
|
||||
RFI_FONT_FILE_NOT_FOUND_ERROR = 2,
|
||||
RFI_MISSING_FONT_TABLE_ERROR = 3,
|
||||
RFI_OUT_OF_MEMORY_ERROR = 4
|
||||
};
|
||||
|
||||
class RenderingFontInstance : public LEFontInstance
|
||||
{
|
||||
protected:
|
||||
void *fSurface;
|
||||
|
||||
le_int32 fPointSize;
|
||||
le_int32 fUnitsPerEM;
|
||||
le_int32 fAscent;
|
||||
le_int32 fDescent;
|
||||
le_int32 fLeading;
|
||||
|
||||
TableCacheEntry *fTableCache;
|
||||
le_int32 fTableCacheCurr;
|
||||
le_int32 fTableCacheSize;
|
||||
|
||||
CMAPMapper *fMapper;
|
||||
|
||||
virtual RFIErrorCode initMapper();
|
||||
virtual RFIErrorCode initFontTableCache();
|
||||
virtual void flushFontTableCache();
|
||||
virtual const void *readFontTable(LETag tableTag) const = 0;
|
||||
|
||||
public:
|
||||
RenderingFontInstance(void *surface, le_int16 pointSize);
|
||||
|
||||
virtual ~RenderingFontInstance();
|
||||
|
||||
virtual const void *getFontTable(LETag tableTag) const;
|
||||
|
||||
virtual le_bool canDisplay(LEUnicode32 ch) const
|
||||
{
|
||||
return fMapper->unicodeToGlyph(ch) != 0;
|
||||
};
|
||||
|
||||
virtual le_int32 getUnitsPerEM() const
|
||||
{
|
||||
return fUnitsPerEM;
|
||||
};
|
||||
|
||||
virtual le_int32 getLineHeight() const
|
||||
{
|
||||
return getAscent() + getDescent() + getLeading();
|
||||
};
|
||||
|
||||
virtual le_int32 getAscent() const
|
||||
{
|
||||
return fAscent;
|
||||
};
|
||||
|
||||
virtual le_int32 getDescent() const
|
||||
{
|
||||
return fDescent;
|
||||
};
|
||||
|
||||
virtual le_int32 getLeading() const
|
||||
{
|
||||
return fLeading;
|
||||
};
|
||||
|
||||
virtual void mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, const LECharMapper *mapper, LEGlyphID glyphs[]) const;
|
||||
|
||||
virtual LEGlyphID mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper) const;
|
||||
|
||||
virtual le_int32 getName(le_uint16 platformID, le_uint16 scriptID, le_uint16 languageID, le_uint16 nameID, LEUnicode *name) const
|
||||
{
|
||||
// This is only used for CDAC fonts, and we'll have to loose that support anyhow...
|
||||
//return (le_int32) fFontObject->getName(platformID, scriptID, languageID, nameID, name);
|
||||
if (name != NULL) {
|
||||
*name = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
virtual void getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const = 0;
|
||||
|
||||
virtual le_bool getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point) const = 0;
|
||||
|
||||
virtual const void setFont(void *surface) const
|
||||
{
|
||||
// default implementation is to ignore this
|
||||
};
|
||||
|
||||
virtual void drawGlyphs(void *surface, LEGlyphID *glyphs, le_uint32 count, le_int32 *dx,
|
||||
le_int32 x, le_int32 y, le_int32 width, le_int32 height) const = 0;
|
||||
|
||||
float getXPixelsPerEm() const
|
||||
{
|
||||
return (float) fPointSize;
|
||||
};
|
||||
|
||||
float getYPixelsPerEm() const
|
||||
{
|
||||
return (float) fPointSize;
|
||||
};
|
||||
|
||||
float xUnitsToPoints(float xUnits) const
|
||||
{
|
||||
return (xUnits * fPointSize) / (float) fUnitsPerEM;
|
||||
};
|
||||
|
||||
float yUnitsToPoints(float yUnits) const
|
||||
{
|
||||
return (yUnits * fPointSize) / (float) fUnitsPerEM;
|
||||
};
|
||||
|
||||
void unitsToPoints(LEPoint &units, LEPoint &points) const
|
||||
{
|
||||
points.fX = xUnitsToPoints(units.fX);
|
||||
points.fY = yUnitsToPoints(units.fY);
|
||||
}
|
||||
|
||||
float xPixelsToUnits(float xPixels) const
|
||||
{
|
||||
return (xPixels * fUnitsPerEM) / (float) fPointSize;
|
||||
};
|
||||
|
||||
float yPixelsToUnits(float yPixels) const
|
||||
{
|
||||
return (yPixels * fUnitsPerEM) / (float) fPointSize;
|
||||
};
|
||||
|
||||
void pixelsToUnits(LEPoint &pixels, LEPoint &units) const
|
||||
{
|
||||
units.fX = xPixelsToUnits(pixels.fX);
|
||||
units.fY = yPixelsToUnits(pixels.fY);
|
||||
};
|
||||
|
||||
void transformFunits(float xFunits, float yFunits, LEPoint &pixels) const
|
||||
{
|
||||
pixels.fX = xUnitsToPoints(xFunits);
|
||||
pixels.fY = yUnitsToPoints(yFunits);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
28
icu4c/source/samples/layout/Sample.utf8
Normal file
28
icu4c/source/samples/layout/Sample.utf8
Normal file
|
@ -0,0 +1,28 @@
|
|||
The LayoutEngine does all the work necessary to display Unicode text written in languages with complex
|
||||
writing systems such as Hindi (हिन्दी)
|
||||
Thai (ไทย) and Arabic (العربية). Here's a sample of some text written in Sanskrit:
|
||||
श्रीमद् भगवद्गीता
|
||||
अध्याय अर्जुन विषाद
|
||||
योग धृतराष्ट्र उवाचृ
|
||||
धर्मक्षेत्रे
|
||||
कुरुक्षेत्रे समवेता
|
||||
युयुत्सवः मामकाः
|
||||
पाण्डवाश्चैव किमकुर्वत
|
||||
संजव Here's a sample of some text written in Arabic:
|
||||
أساسًا، تتعامل
|
||||
الحواسيب فقط مع
|
||||
الأرقام، وتقوم ب
|
||||
تخزين الأحرف والمحارف ال
|
||||
أخرى بعد أن تُعطي رقما م
|
||||
عينا لكل واحد من
|
||||
ها. وقبل اختراع
|
||||
"يونِكود"، كان ه
|
||||
ناك مئات الأنظمة
|
||||
للتشفير وتخصيص
|
||||
هذه الأر
|
||||
قام للمح
|
||||
ارف، ولم يوجد نظ
|
||||
ام تشفير واحد يح
|
||||
توي على جميع المحارف الض
|
||||
رورية and here's a sample of some text written in Thai:
|
||||
บทที่๑พายุไซโคลนโดโรธีอาศัยอยู่ท่ามกลางทุ่งใหญ่ในแคนซัสกับลุงเฮนรีชาวไร่และป้าเอ็มภรรยาชาวไร่บ้านของพวกเขาหลังเล็กเพราะไม้สร้างบ้านต้องขนมาด้วยเกวียนเป็นระยะทางหลายไมล์
|
116
icu4c/source/samples/layout/UnicodeReader.cpp
Normal file
116
icu4c/source/samples/layout/UnicodeReader.cpp
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Copyright (C) 1998-2001, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#include "unicode/unistr.h"
|
||||
|
||||
#include "GUISupport.h"
|
||||
#include "UnicodeReader.h"
|
||||
|
||||
|
||||
/*
|
||||
* Read the text from a file. The text must start with a Unicode Byte
|
||||
* Order Mark (BOM) so that we know what order to read the bytes in.
|
||||
*/
|
||||
const UChar *UnicodeReader::readFile(const char *fileName, GUISupport *guiSupport, int32_t &charCount)
|
||||
{
|
||||
FILE *f;
|
||||
int32_t fileSize;
|
||||
|
||||
UChar *charBuffer;
|
||||
char *byteBuffer;
|
||||
char startBytes[4] = {'\xA5', '\xA5', '\xA5', '\xA5'};
|
||||
char errorMessage[128];
|
||||
char *cp = "";
|
||||
int32_t signatureLength = 0;
|
||||
|
||||
f = fopen(fileName, "rb");
|
||||
|
||||
if( f == NULL ) {
|
||||
sprintf(errorMessage,"Couldn't open %s: %s \n", fileName, strerror(errno));
|
||||
guiSupport->postErrorMessage(errorMessage, "Text File Error");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
fileSize = ftell(f);
|
||||
|
||||
fseek(f, 0, SEEK_SET);
|
||||
fread(startBytes, sizeof(char), 4, f);
|
||||
|
||||
if (startBytes[0] == '\xFE' && startBytes[1] == '\xFF') {
|
||||
cp = "UTF-16BE";
|
||||
signatureLength = 2;
|
||||
} else if (startBytes[0] == '\xFF' && startBytes[1] == '\xFE') {
|
||||
if (startBytes[2] == '\x00' && startBytes[3] == '\x00') {
|
||||
cp = "UTF-32LE";
|
||||
signatureLength = 4;
|
||||
} else {
|
||||
cp = "UTF-16LE";
|
||||
signatureLength = 2;
|
||||
}
|
||||
} else if (startBytes[0] == '\xEF' && startBytes[1] == '\xBB' && startBytes[2] == '\xBF') {
|
||||
cp = "UTF-8";
|
||||
signatureLength = 3;
|
||||
} else if (startBytes[0] == '\x0E' && startBytes[1] == '\xFE' && startBytes[2] == '\xFF') {
|
||||
cp = "SCSU";
|
||||
signatureLength = 3;
|
||||
} else if (startBytes[0] == '\x00' && startBytes[1] == '\x00' &&
|
||||
startBytes[2] == '\xFE' && startBytes[3] == '\xFF') {
|
||||
cp = "UTF-32BE";
|
||||
signatureLength = 4;
|
||||
} else {
|
||||
sprintf(errorMessage, "Couldn't detect the encoding of %s: (%2.2X, %2.2X, %2.2X, %2.2X)\n", fileName,
|
||||
startBytes[0], startBytes[1], startBytes[2], startBytes[3]);
|
||||
guiSupport->postErrorMessage(errorMessage, "Text File Error");
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fileSize -= signatureLength;
|
||||
fseek(f, signatureLength, SEEK_SET);
|
||||
byteBuffer = new char[fileSize];
|
||||
|
||||
if(byteBuffer == 0) {
|
||||
sprintf(errorMessage,"Couldn't get memory for reading %s: %s \n", fileName, strerror(errno));
|
||||
guiSupport->postErrorMessage(errorMessage, "Text File Error");
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fread(byteBuffer, sizeof(char), fileSize, f);
|
||||
if( ferror(f) ) {
|
||||
sprintf(errorMessage,"Couldn't read %s: %s \n", fileName, strerror(errno));
|
||||
guiSupport->postErrorMessage(errorMessage, "Text File Error");
|
||||
fclose(f);
|
||||
delete[] byteBuffer;
|
||||
return 0;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
UnicodeString myText(byteBuffer, fileSize, cp);
|
||||
|
||||
delete[] byteBuffer;
|
||||
|
||||
charCount = myText.length();
|
||||
charBuffer = new UChar[charCount];
|
||||
if(charBuffer == 0) {
|
||||
sprintf(errorMessage,"Couldn't get memory for reading %s: %s \n", fileName, strerror(errno));
|
||||
guiSupport->postErrorMessage(errorMessage, "Text File Error");
|
||||
return 0;
|
||||
}
|
||||
|
||||
myText.extract(0, myText.length(), charBuffer);
|
||||
charBuffer[charCount + 1] = 0; // NULL terminate for easier reading in the debugger
|
||||
|
||||
return charBuffer;
|
||||
}
|
||||
|
32
icu4c/source/samples/layout/UnicodeReader.h
Normal file
32
icu4c/source/samples/layout/UnicodeReader.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Copyright (C) 1998-2001, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __UNICODEREADER_H
|
||||
#define __UNICODEREADER_H
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#include "GUISupport.h"
|
||||
|
||||
class UnicodeReader
|
||||
{
|
||||
public:
|
||||
UnicodeReader()
|
||||
{
|
||||
// nothing...
|
||||
}
|
||||
|
||||
~UnicodeReader()
|
||||
{
|
||||
// nothing, too
|
||||
}
|
||||
|
||||
static const UChar *readFile(const char *fileName, GUISupport *guiSupport, int32_t &charCount);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
203
icu4c/source/samples/layout/cmaps.cpp
Normal file
203
icu4c/source/samples/layout/cmaps.cpp
Normal file
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
****************************************************************************** *
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
****************************************************************************** *
|
||||
* file name: cmaps.cpp
|
||||
*
|
||||
* created on: ??/??/2001
|
||||
* created by: Eric R. Mader
|
||||
*/
|
||||
|
||||
#include "layout/LETypes.h"
|
||||
#include "layout/LESwaps.h"
|
||||
|
||||
#include "sfnt.h"
|
||||
#include "cmaps.h"
|
||||
|
||||
//
|
||||
// Finds the high bit by binary searching
|
||||
// through the bits in value.
|
||||
//
|
||||
le_uint8 highBit(le_uint32 value)
|
||||
{
|
||||
le_uint8 bit = 0;
|
||||
|
||||
if (value >= 1 << 16) {
|
||||
value >>= 16;
|
||||
bit += 16;
|
||||
}
|
||||
|
||||
if (value >= 1 << 8) {
|
||||
value >>= 8;
|
||||
bit += 8;
|
||||
}
|
||||
|
||||
if (value >= 1 << 4) {
|
||||
value >>= 4;
|
||||
bit += 4;
|
||||
}
|
||||
|
||||
if (value >= 1 << 2) {
|
||||
value >>= 2;
|
||||
bit += 2;
|
||||
}
|
||||
|
||||
if (value >= 1 << 1) {
|
||||
value >>= 1;
|
||||
bit += 1;
|
||||
}
|
||||
|
||||
return bit;
|
||||
}
|
||||
|
||||
CMAPMapper *CMAPMapper::createUnicodeMapper(const CMAPTable *cmap)
|
||||
{
|
||||
le_uint16 i;
|
||||
le_uint16 nSubtables = SWAPW(cmap->numberSubtables);
|
||||
const CMAPEncodingSubtable *subtable = NULL;
|
||||
le_uint32 offset1 = 0, offset10 = 0;
|
||||
|
||||
for (i = 0; i < nSubtables; i += 1) {
|
||||
const CMAPEncodingSubtableHeader *esh = &cmap->encodingSubtableHeaders[i];
|
||||
|
||||
if (SWAPW(esh->platformID) == 3) {
|
||||
switch (SWAPW(esh->platformSpecificID)) {
|
||||
case 1:
|
||||
offset1 = SWAPL(esh->encodingOffset);
|
||||
break;
|
||||
|
||||
case 10:
|
||||
offset10 = SWAPL(esh->encodingOffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (offset10 != 0)
|
||||
{
|
||||
subtable = (const CMAPEncodingSubtable *) ((const char *) cmap + offset10);
|
||||
} else if (offset1 != 0) {
|
||||
subtable = (const CMAPEncodingSubtable *) ((const char *) cmap + offset1);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (SWAPW(subtable->format)) {
|
||||
case 4:
|
||||
return new CMAPFormat4Mapper(cmap, (const CMAPFormat4Encoding *) subtable);
|
||||
|
||||
case 12:
|
||||
{
|
||||
const CMAPFormat12Encoding *encoding = (const CMAPFormat12Encoding *) subtable;
|
||||
|
||||
return new CMAPGroupMapper(cmap, encoding->groups, SWAPL(encoding->nGroups));
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CMAPFormat4Mapper::CMAPFormat4Mapper(const CMAPTable *cmap, const CMAPFormat4Encoding *header)
|
||||
: CMAPMapper(cmap)
|
||||
{
|
||||
le_uint16 segCount = SWAPW(header->segCountX2) / 2;
|
||||
|
||||
fEntrySelector = SWAPW(header->entrySelector);
|
||||
fRangeShift = SWAPW(header->rangeShift) / 2;
|
||||
fEndCodes = &header->endCodes[0];
|
||||
fStartCodes = &header->endCodes[segCount + 1]; // + 1 for reservedPad...
|
||||
fIdDelta = &fStartCodes[segCount];
|
||||
fIdRangeOffset = &fIdDelta[segCount];
|
||||
}
|
||||
|
||||
LEGlyphID CMAPFormat4Mapper::unicodeToGlyph(LEUnicode32 unicode32) const
|
||||
{
|
||||
if (unicode32 >= 0x10000) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
LEUnicode16 unicode = (LEUnicode16) unicode32;
|
||||
le_uint16 index = 0;
|
||||
le_uint16 probe = 1 << fEntrySelector;
|
||||
LEGlyphID result = 0;
|
||||
|
||||
if (SWAPW(fStartCodes[fRangeShift]) <= unicode) {
|
||||
index = fRangeShift;
|
||||
}
|
||||
|
||||
while (probe > (1 << 0)) {
|
||||
probe >>= 1;
|
||||
|
||||
if (SWAPW(fStartCodes[index + probe]) <= unicode) {
|
||||
index += probe;
|
||||
}
|
||||
}
|
||||
|
||||
if (unicode >= SWAPW(fStartCodes[index]) && unicode <= SWAPW(fEndCodes[index])) {
|
||||
if (fIdRangeOffset[index] == 0) {
|
||||
result = (LEGlyphID) unicode;
|
||||
} else {
|
||||
le_uint16 offset = unicode - SWAPW(fStartCodes[index]);
|
||||
le_uint16 rangeOffset = SWAPW(fIdRangeOffset[index]);
|
||||
le_uint16 *glyphIndexTable = (le_uint16 *) ((char *) &fIdRangeOffset[index] + rangeOffset);
|
||||
|
||||
result = SWAPW(glyphIndexTable[offset]);
|
||||
}
|
||||
|
||||
result += SWAPW(fIdDelta[index]);
|
||||
} else {
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CMAPFormat4Mapper::~CMAPFormat4Mapper()
|
||||
{
|
||||
// parent destructor does it all
|
||||
}
|
||||
|
||||
CMAPGroupMapper::CMAPGroupMapper(const CMAPTable *cmap, const CMAPGroup *groups, le_uint32 nGroups)
|
||||
: CMAPMapper(cmap), fGroups(groups)
|
||||
{
|
||||
le_uint8 bit = highBit(nGroups);
|
||||
fPower = 1 << bit;
|
||||
fRangeOffset = nGroups - fPower;
|
||||
}
|
||||
|
||||
LEGlyphID CMAPGroupMapper::unicodeToGlyph(LEUnicode32 unicode32) const
|
||||
{
|
||||
le_int32 probe = fPower;
|
||||
le_int32 range = 0;
|
||||
|
||||
if (SWAPL(fGroups[fRangeOffset].startCharCode) <= unicode32) {
|
||||
range = fRangeOffset;
|
||||
}
|
||||
|
||||
while (probe > (1 << 0)) {
|
||||
probe >>= 1;
|
||||
|
||||
if (SWAPL(fGroups[range + probe].startCharCode) <= unicode32) {
|
||||
range += probe;
|
||||
}
|
||||
}
|
||||
|
||||
if (SWAPL(fGroups[range].startCharCode) <= unicode32 && SWAPL(fGroups[range].endCharCode) >= unicode32) {
|
||||
return (LEGlyphID) (SWAPL(fGroups[range].startGlyphCode) + unicode32 - SWAPL(fGroups[range].startCharCode));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CMAPGroupMapper::~CMAPGroupMapper()
|
||||
{
|
||||
// parent destructor does it all
|
||||
}
|
||||
|
89
icu4c/source/samples/layout/cmaps.h
Normal file
89
icu4c/source/samples/layout/cmaps.h
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
****************************************************************************** *
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
****************************************************************************** *
|
||||
* file name: cmaps.h
|
||||
*
|
||||
* created on: ??/??/2001
|
||||
* created by: Eric R. Mader
|
||||
*/
|
||||
|
||||
#ifndef __CMAPS_H
|
||||
#define __CMAPS_H
|
||||
|
||||
#include "layout/LETypes.h"
|
||||
#include "sfnt.h"
|
||||
|
||||
class CMAPMapper
|
||||
{
|
||||
public:
|
||||
virtual LEGlyphID unicodeToGlyph(LEUnicode32 unicode32) const = 0;
|
||||
|
||||
virtual ~CMAPMapper();
|
||||
|
||||
static CMAPMapper *createUnicodeMapper(const CMAPTable *cmap);
|
||||
|
||||
protected:
|
||||
CMAPMapper(const CMAPTable *cmap);
|
||||
|
||||
CMAPMapper() {};
|
||||
|
||||
private:
|
||||
const CMAPTable *fcmap;
|
||||
};
|
||||
|
||||
class CMAPFormat4Mapper : public CMAPMapper
|
||||
{
|
||||
public:
|
||||
CMAPFormat4Mapper(const CMAPTable *cmap, const CMAPFormat4Encoding *header);
|
||||
|
||||
virtual ~CMAPFormat4Mapper();
|
||||
|
||||
virtual LEGlyphID unicodeToGlyph(LEUnicode32 unicode32) const;
|
||||
|
||||
protected:
|
||||
CMAPFormat4Mapper() {};
|
||||
|
||||
private:
|
||||
le_uint16 fEntrySelector;
|
||||
le_uint16 fRangeShift;
|
||||
const le_uint16 *fEndCodes;
|
||||
const le_uint16 *fStartCodes;
|
||||
const le_uint16 *fIdDelta;
|
||||
const le_uint16 *fIdRangeOffset;
|
||||
};
|
||||
|
||||
class CMAPGroupMapper : public CMAPMapper
|
||||
{
|
||||
public:
|
||||
CMAPGroupMapper(const CMAPTable *cmap, const CMAPGroup *groups, le_uint32 nGroups);
|
||||
|
||||
virtual ~CMAPGroupMapper();
|
||||
|
||||
virtual LEGlyphID unicodeToGlyph(LEUnicode32 unicode32) const;
|
||||
|
||||
protected:
|
||||
CMAPGroupMapper() {};
|
||||
|
||||
private:
|
||||
le_int32 fPower;
|
||||
le_int32 fRangeOffset;
|
||||
const CMAPGroup *fGroups;
|
||||
};
|
||||
|
||||
inline CMAPMapper::CMAPMapper(const CMAPTable *cmap)
|
||||
: fcmap(cmap)
|
||||
{
|
||||
// nothing else to do
|
||||
}
|
||||
|
||||
inline CMAPMapper::~CMAPMapper()
|
||||
{
|
||||
delete[] (char *) fcmap;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
201
icu4c/source/samples/layout/gnomelayout.cpp
Normal file
201
icu4c/source/samples/layout/gnomelayout.cpp
Normal file
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
****************************************************************************** *
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
****************************************************************************** *
|
||||
* file name: gnomelayout.cpp
|
||||
*
|
||||
* created on: 09/04/2001
|
||||
* created by: Eric R. Mader
|
||||
*/
|
||||
|
||||
#include <gnome.h>
|
||||
#include "freetype/freetype.h"
|
||||
|
||||
#include "unicode/ustring.h"
|
||||
#include "unicode/uscript.h"
|
||||
|
||||
#include "unicode/loengine.h"
|
||||
|
||||
#include "GnomeFontInstance.h"
|
||||
|
||||
#include "paragraph.h"
|
||||
|
||||
#include "GnomeGUISupport.h"
|
||||
#include "GnomeFontMap.h"
|
||||
#include "UnicodeReader.h"
|
||||
#include "scrptrun.h"
|
||||
|
||||
#define ARRAY_LENGTH(array) (sizeof array / sizeof array[0])
|
||||
|
||||
void showabout(GtkWidget *widget, gpointer data)
|
||||
{
|
||||
GtkWidget *aboutBox;
|
||||
const gchar *writtenBy[] = {
|
||||
"Eric Mader",
|
||||
NULL
|
||||
};
|
||||
|
||||
aboutBox = gnome_about_new("Gnome Layout Demo",
|
||||
"0.1",
|
||||
"Copyright (C) 1998-2001 By International Business Machines Corporation and others. All Rights Reserved.",
|
||||
writtenBy,
|
||||
"A simple demo of the ICU LayoutEngine.",
|
||||
NULL);
|
||||
|
||||
gtk_widget_show(aboutBox);
|
||||
}
|
||||
|
||||
void notimpl(GtkObject *object, gpointer data)
|
||||
{
|
||||
gnome_ok_dialog("Not implemented...");
|
||||
}
|
||||
|
||||
void shutdown(GtkObject *object, gpointer data)
|
||||
{
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
GnomeUIInfo fileMenu[] =
|
||||
{
|
||||
GNOMEUIINFO_MENU_OPEN_ITEM(notimpl, NULL),
|
||||
GNOMEUIINFO_SEPARATOR,
|
||||
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_("File"), fileMenu),
|
||||
GNOMEUIINFO_SUBTREE(N_("Help"), helpMenu),
|
||||
GNOMEUIINFO_END
|
||||
};
|
||||
|
||||
struct Context
|
||||
{
|
||||
long width;
|
||||
long height;
|
||||
Paragraph *paragraph;
|
||||
};
|
||||
|
||||
gint eventDelete(GtkWidget *widget, GdkEvent *event, gpointer data)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gint eventDestroy(GtkWidget *widget, GdkEvent *event, Context *context)
|
||||
{
|
||||
shutdown(GTK_OBJECT(widget), context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
gint eventConfigure(GtkWidget *widget, GdkEventConfigure *event, Context *context)
|
||||
{
|
||||
context->width = event->width;
|
||||
context->height = event->height;
|
||||
|
||||
if (context->width > 0 && context->height > 0) {
|
||||
context->paragraph->breakLines(context->width, context->height);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gint eventExpose(GtkWidget *widget, GdkEvent *event, Context *context)
|
||||
{
|
||||
gint maxLines = context->paragraph->getLineCount() - 1;
|
||||
gint firstLine = 0, lastLine = context->height / context->paragraph->getLineHeight();
|
||||
|
||||
context->paragraph->draw(widget, firstLine, (maxLines < lastLine)? maxLines : lastLine);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
GtkWidget *app;
|
||||
GtkWidget *area;
|
||||
GtkStyle *style;
|
||||
unsigned short status = 0;
|
||||
Context context = {600, 400, NULL};
|
||||
TT_Engine engine;
|
||||
|
||||
TT_Init_FreeType(&engine);
|
||||
|
||||
RFIErrorCode fontStatus = RFI_NO_ERROR;
|
||||
GnomeGUISupport *guiSupport = new GnomeGUISupport();
|
||||
GnomeFontMap *fontMap = new GnomeFontMap(engine, "FontMap.Gnome", 24, guiSupport, fontStatus);
|
||||
|
||||
if (LE_FAILURE(fontStatus)) {
|
||||
TT_Done_FreeType(engine);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// FIXME: is it cheating to pass NULL for surface, since we know that
|
||||
// GnomeFontInstance won't use it?
|
||||
context.paragraph = Paragraph::paragraphFactory("Sample.utf8", fontMap, guiSupport, NULL);
|
||||
|
||||
if (context.paragraph != NULL) {
|
||||
gnome_init("gnomelayout", "1.0", argc, argv);
|
||||
app = gnome_app_new("gnomelayout", "Gnome Layout");
|
||||
|
||||
gtk_window_set_default_size(GTK_WINDOW(app), 600 - 24, 400);
|
||||
|
||||
gnome_app_create_menus(GNOME_APP(app), mainMenu);
|
||||
|
||||
gtk_signal_connect(GTK_OBJECT(app),
|
||||
"delete_event",
|
||||
GTK_SIGNAL_FUNC(eventDelete),
|
||||
NULL);
|
||||
|
||||
gtk_signal_connect(GTK_OBJECT(app),
|
||||
"destroy",
|
||||
GTK_SIGNAL_FUNC(eventDestroy),
|
||||
&context);
|
||||
|
||||
area = gtk_drawing_area_new();
|
||||
|
||||
#if 1
|
||||
style = gtk_style_copy(gtk_widget_get_style(area));
|
||||
|
||||
for (int i = 0; i < 5; i += 1) {
|
||||
style->fg[i] =style->white;
|
||||
}
|
||||
|
||||
gtk_widget_set_style(area, style);
|
||||
#endif
|
||||
|
||||
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);
|
||||
|
||||
gtk_widget_show_all(app);
|
||||
|
||||
gtk_main();
|
||||
|
||||
delete context.paragraph;
|
||||
}
|
||||
|
||||
delete fontMap;
|
||||
|
||||
TT_Done_FreeType(engine);
|
||||
|
||||
exit(0);
|
||||
}
|
246
icu4c/source/samples/layout/layout.cpp
Normal file
246
icu4c/source/samples/layout/layout.cpp
Normal file
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, 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 "LETypes.h"
|
||||
//#include "LEFontInstance.h"
|
||||
//#include "LayoutEngine.h"
|
||||
//#include "unicode/loengine.h"
|
||||
#include "unicode/uscript.h"
|
||||
//#include "LEScripts.h"
|
||||
|
||||
#include "GDIFontInstance.h"
|
||||
|
||||
#include "paragraph.h"
|
||||
|
||||
#include "GDIGUISupport.h"
|
||||
#include "GDIFontMap.h"
|
||||
#include "UnicodeReader.h"
|
||||
#include "scrptrun.h"
|
||||
|
||||
#define ARRAY_LENGTH(array) (sizeof array / sizeof array[0])
|
||||
|
||||
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
|
||||
|
||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
|
||||
{
|
||||
HWND hwnd;
|
||||
MSG msg;
|
||||
WNDCLASS wndclass;
|
||||
TCHAR szAppName[] = TEXT("LayoutDemo");
|
||||
TCHAR szTitle[] = TEXT("LayoutDemo: Demo of LayoutEngine");
|
||||
RFIErrorCode status = RFI_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 = NULL;
|
||||
wndclass.lpszClassName = szAppName;
|
||||
|
||||
if (!RegisterClass(&wndclass)) {
|
||||
MessageBox(NULL, TEXT("This demo only runs on Windows 2000!"), szAppName, MB_ICONERROR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
hwnd = CreateWindow(szAppName, szTitle,
|
||||
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)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
return msg.wParam;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
HDC hdc;
|
||||
Paragraph *paragraph;
|
||||
static le_int32 windowCount = 0;
|
||||
static GDIFontMap *fontMap = NULL;
|
||||
static GDIGUISupport *guiSupport = new GDIGUISupport();
|
||||
|
||||
switch (message) {
|
||||
case WM_CREATE:
|
||||
{
|
||||
RFIErrorCode fontStatus = RFI_NO_ERROR;
|
||||
|
||||
hdc = GetDC(hwnd);
|
||||
|
||||
fontMap = new GDIFontMap(hdc, "FontMap.GDI", 24, guiSupport, fontStatus);
|
||||
|
||||
if (LE_FAILURE(fontStatus)) {
|
||||
ReleaseDC(hwnd, hdc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
paragraph = Paragraph::paragraphFactory("Sample.utf8", fontMap, guiSupport, hdc);
|
||||
SetWindowLong(hwnd, 0, (LONG) paragraph);
|
||||
|
||||
windowCount += 1;
|
||||
ReleaseDC(hwnd, hdc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_SIZE:
|
||||
{
|
||||
le_int32 width = LOWORD(lParam);
|
||||
le_int32 height = HIWORD(lParam);
|
||||
SCROLLINFO si;
|
||||
|
||||
|
||||
paragraph = (Paragraph *) GetWindowLong(hwnd, 0);
|
||||
|
||||
if (paragraph != NULL) {
|
||||
// FIXME: does it matter what we put in the ScrollInfo
|
||||
// if the window's been minimized?
|
||||
if (width > 0 && height > 0) {
|
||||
paragraph->breakLines(width, height);
|
||||
}
|
||||
|
||||
si.cbSize = sizeof si;
|
||||
si.fMask = SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL;
|
||||
si.nMin = 0;
|
||||
si.nMax = paragraph->getLineCount() - 1;
|
||||
si.nPage = height / paragraph->getLineHeight();
|
||||
SetScrollInfo(hwnd, SB_VERT, &si, true);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
paragraph = (Paragraph *) GetWindowLong(hwnd, 0);
|
||||
|
||||
if (paragraph != NULL && si.nPos != vertPos) {
|
||||
ScrollWindow(hwnd, 0, paragraph->getLineHeight() * (vertPos - si.nPos), NULL, NULL);
|
||||
UpdateWindow(hwnd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_PAINT:
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
SCROLLINFO si;
|
||||
le_int32 firstLine, lastLine;
|
||||
|
||||
hdc = BeginPaint(hwnd, &ps);
|
||||
|
||||
si.cbSize = sizeof si;
|
||||
si.fMask = SIF_ALL;
|
||||
GetScrollInfo(hwnd, SB_VERT, &si);
|
||||
|
||||
firstLine = si.nPos;
|
||||
|
||||
paragraph = (Paragraph *) GetWindowLong(hwnd, 0);
|
||||
|
||||
if (paragraph != NULL) {
|
||||
// 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, paragraph->getLineCount() - 1);
|
||||
|
||||
paragraph->draw(hdc, firstLine, lastLine);
|
||||
}
|
||||
|
||||
EndPaint(hwnd, &ps);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_DESTROY:
|
||||
{
|
||||
paragraph = (Paragraph *) GetWindowLong(hwnd, 0);
|
||||
|
||||
if (paragraph != NULL) {
|
||||
delete paragraph;
|
||||
}
|
||||
|
||||
if (--windowCount <= 0) {
|
||||
delete fontMap;
|
||||
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
return DefWindowProc(hwnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
184
icu4c/source/samples/layout/layout.dsp
Normal file
184
icu4c/source/samples/layout/layout.dsp
Normal file
|
@ -0,0 +1,184 @@
|
|||
# Microsoft Developer Studio Project File - Name="layout" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=layout - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "layout.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "layout.mak" CFG="layout - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "layout - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "layout - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "layout - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /I "..\..\..\include" /I "..\..\..\include\layout" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "UNICODE" /D _WIN32_WINNT=0X500 /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 ..\..\..\lib\icule.lib ..\..\..\lib\icuuc.lib ..\..\..\lib\icuin.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "layout - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\include" /I "..\..\..\include\layout" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "UNICODE" /D _WIN32_WINNT=0X500 /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 ..\..\..\lib\iculed.lib ..\..\..\lib\icuucd.lib ..\..\..\lib\icuind.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "layout - Win32 Release"
|
||||
# Name "layout - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cmaps.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\FontMap.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\GDIFontInstance.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\GDIFontMap.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\GDIGUISupport.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\layout.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\paragraph.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\RenderingFontInstance.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\scrptrun.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\UnicodeReader.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cmaps.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\FontMap.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\GDIFontInstance.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\GDIFontMap.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\GDIGUISupport.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\GUISupport.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\paragraph.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\RenderingFontInstance.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\scrptrun.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sfnt.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\UnicodeReader.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
29
icu4c/source/samples/layout/layout.dsw
Normal file
29
icu4c/source/samples/layout/layout.dsw
Normal file
|
@ -0,0 +1,29 @@
|
|||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "layout"=.\layout.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
481
icu4c/source/samples/layout/paragraph.cpp
Normal file
481
icu4c/source/samples/layout/paragraph.cpp
Normal file
|
@ -0,0 +1,481 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
*******************************************************************************
|
||||
* file name: Paragraph.cpp
|
||||
*
|
||||
* created on: 09/06/2000
|
||||
* created by: Eric R. Mader
|
||||
*/
|
||||
|
||||
#include "unicode/loengine.h"
|
||||
|
||||
#include "RenderingFontInstance.h"
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#include "unicode/unicode.h"
|
||||
#include "unicode/uchriter.h"
|
||||
#include "unicode/brkiter.h"
|
||||
#include "unicode/locid.h"
|
||||
|
||||
#include "paragraph.h"
|
||||
#include "scrptrun.h"
|
||||
#include "UnicodeReader.h"
|
||||
#include "FontMap.h"
|
||||
|
||||
#define MARGIN 10
|
||||
|
||||
Paragraph::Paragraph(void *surface, RunParams params[], int32_t count)
|
||||
: fRunCount(count), fRunInfo(NULL), fCharCount(0), fText(NULL), fGlyphCount(0), fGlyphs(NULL),
|
||||
fCharIndices(NULL), fGlyphIndices(NULL), fDX(NULL), fBreakArray(NULL), fBreakCount(0),
|
||||
fLineHeight(-1), fAscent(-1)
|
||||
{
|
||||
int32_t i;
|
||||
|
||||
fWidth = fHeight = 0;
|
||||
|
||||
fRunInfo = new RunInfo[count + 1];
|
||||
|
||||
// Set charBase and rightToLeft for
|
||||
// each run and count the total characters
|
||||
for (i = 0; i < count; i += 1) {
|
||||
fRunInfo[i].charBase = fCharCount;
|
||||
fRunInfo[i].rightToLeft = params[i].rightToLeft;
|
||||
fCharCount += params[i].count;
|
||||
}
|
||||
|
||||
// Set charBase and rightToLeft for the
|
||||
// fake run at the end.
|
||||
fRunInfo[count].charBase = fCharCount;
|
||||
fRunInfo[count].rightToLeft = false;
|
||||
|
||||
fBreakArray = new int32_t[fCharCount + 1];
|
||||
fText = new LEUnicode[fCharCount];
|
||||
|
||||
// Copy the text runs into a single array
|
||||
for (i = 0; i < count; i += 1) {
|
||||
int32_t charBase = fRunInfo[i].charBase;
|
||||
int32_t charCount = fRunInfo[i + 1].charBase - charBase;
|
||||
|
||||
LE_ARRAY_COPY(&fText[charBase], params[i].text, charCount);
|
||||
}
|
||||
|
||||
Locale thai("th");
|
||||
UCharCharacterIterator *iter = new UCharCharacterIterator(fText, fCharCount);
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
Locale dummyLocale;
|
||||
|
||||
fBrkiter = BreakIterator::createLineInstance(thai, status);
|
||||
fBrkiter->adoptText(iter);
|
||||
|
||||
ICULayoutEngine **engines = new ICULayoutEngine *[count];
|
||||
int32_t maxAscent = -1, maxDescent = -1, maxLeading = -1;
|
||||
float x = 0, y = 0;
|
||||
|
||||
// Layout each run, set glyphBase and glyphCount
|
||||
// and count the total number of glyphs
|
||||
for (i = 0; i < count; i += 1) {
|
||||
int32_t charBase = fRunInfo[i].charBase;
|
||||
int32_t charCount = fRunInfo[i + 1].charBase - charBase;
|
||||
int32_t glyphCount = 0;
|
||||
int32_t runAscent = 0, runDescent = 0, runLeading = 0;
|
||||
UErrorCode success = U_ZERO_ERROR;
|
||||
|
||||
fRunInfo[i].fontInstance = params[i].fontInstance;
|
||||
|
||||
fRunInfo[i].fontInstance->setFont(surface);
|
||||
|
||||
runAscent = fRunInfo[i].fontInstance->getAscent();
|
||||
runDescent = fRunInfo[i].fontInstance->getDescent();
|
||||
runLeading = fRunInfo[i].fontInstance->getLeading();
|
||||
|
||||
|
||||
if (runAscent > maxAscent) {
|
||||
maxAscent = runAscent;
|
||||
}
|
||||
|
||||
if (runDescent > maxDescent) {
|
||||
maxDescent = runDescent;
|
||||
}
|
||||
|
||||
if (runLeading > maxLeading) {
|
||||
maxLeading = runLeading;
|
||||
}
|
||||
|
||||
engines[i] = ICULayoutEngine::createInstance(fRunInfo[i].fontInstance, params[i].scriptCode, dummyLocale, success);
|
||||
|
||||
glyphCount = engines[i]->layoutChars(fText, charBase, charBase + charCount, fCharCount,
|
||||
fRunInfo[i].rightToLeft, x, y, success);
|
||||
|
||||
engines[i]->getGlyphPosition(glyphCount, x, y, success);
|
||||
|
||||
fRunInfo[i].glyphBase = fGlyphCount;
|
||||
fGlyphCount += glyphCount;
|
||||
}
|
||||
|
||||
fLineHeight = maxAscent + maxDescent + maxLeading;
|
||||
fAscent = maxAscent;
|
||||
|
||||
// Set glyphBase for the fake run at the end
|
||||
fRunInfo[count].glyphBase = fGlyphCount;
|
||||
|
||||
fGlyphs = new LEGlyphID[fGlyphCount];
|
||||
fCharIndices = new int32_t[fGlyphCount];
|
||||
fGlyphIndices = new int32_t[fCharCount + 1];
|
||||
fDX = new int32_t[fGlyphCount];
|
||||
fDY = new int32_t[fGlyphCount];
|
||||
|
||||
|
||||
float *positions = new float[fGlyphCount * 2 + 2];
|
||||
|
||||
// Build the glyph, charIndices and positions arrays
|
||||
for (i = 0; i < count; i += 1) {
|
||||
ICULayoutEngine *engine = engines[i];
|
||||
int32_t charBase = fRunInfo[i].charBase;
|
||||
int32_t glyphBase = fRunInfo[i].glyphBase;
|
||||
UErrorCode success = U_ZERO_ERROR;
|
||||
|
||||
engine->getGlyphs(&fGlyphs[glyphBase], success);
|
||||
engine->getCharIndices(&fCharIndices[glyphBase], charBase, success);
|
||||
engine->getGlyphPositions(&positions[glyphBase * 2], success);
|
||||
}
|
||||
|
||||
// Filter deleted glyphs, compute logical advances
|
||||
// and set the char to glyph map
|
||||
for (i = 0; i < fGlyphCount; i += 1) {
|
||||
// Filter deleted glyphs
|
||||
if (fGlyphs[i] == 0xFFFE || fGlyphs[i] == 0xFFFF) {
|
||||
fGlyphs[i] = 0x0001;
|
||||
}
|
||||
|
||||
// compute the logical advance
|
||||
fDX[i] = (int32_t) (positions[i * 2 + 2] - positions[i * 2]);
|
||||
|
||||
// save the Y offset
|
||||
fDY[i] = (int32_t) positions[i * 2 + 1];
|
||||
|
||||
// set char to glyph map
|
||||
fGlyphIndices[fCharIndices[i]] = i;
|
||||
}
|
||||
|
||||
if (fRunInfo[count - 1].rightToLeft) {
|
||||
fGlyphIndices[fCharCount] = fRunInfo[count - 1].glyphBase - 1;
|
||||
} else {
|
||||
fGlyphIndices[fCharCount] = fGlyphCount;
|
||||
}
|
||||
|
||||
delete[] positions;
|
||||
|
||||
// Get rid of the LayoutEngine's:
|
||||
for (i = 0; i < count; i += 1) {
|
||||
delete engines[i];
|
||||
}
|
||||
|
||||
delete[] engines;
|
||||
}
|
||||
|
||||
Paragraph::~Paragraph()
|
||||
{
|
||||
delete[] fDY;
|
||||
delete[] fDX;
|
||||
delete[] fGlyphIndices;
|
||||
delete[] fCharIndices;
|
||||
delete[] fGlyphs;
|
||||
|
||||
delete fBrkiter;
|
||||
delete fText;
|
||||
|
||||
delete[] fBreakArray;
|
||||
delete[] fRunInfo;
|
||||
}
|
||||
|
||||
int32_t Paragraph::getLineHeight()
|
||||
{
|
||||
return fLineHeight;
|
||||
}
|
||||
|
||||
int32_t Paragraph::getLineCount()
|
||||
{
|
||||
return fBreakCount;
|
||||
}
|
||||
|
||||
int32_t Paragraph::getAscent()
|
||||
{
|
||||
return fAscent;
|
||||
}
|
||||
|
||||
int32_t Paragraph::previousBreak(int32_t charIndex)
|
||||
{
|
||||
LEUnicode ch = fText[charIndex];
|
||||
|
||||
// skip over any whitespace or control
|
||||
// characters, because they can hang in
|
||||
// the margin.
|
||||
while (charIndex < fCharCount &&
|
||||
(Unicode::isWhitespace(ch) ||
|
||||
Unicode::isControl(ch))) {
|
||||
ch = fText[++charIndex];
|
||||
}
|
||||
|
||||
// return the break location that's at or before
|
||||
// the character we stopped on. Note: if we're
|
||||
// on a break, the "+ 1" will cause preceding to
|
||||
// back up to it.
|
||||
return fBrkiter->preceding(charIndex + 1);
|
||||
}
|
||||
|
||||
void Paragraph::breakLines(int32_t width, int32_t height)
|
||||
{
|
||||
int32_t lineWidth = width - (2 * MARGIN);
|
||||
int32_t thisWidth = 0;
|
||||
int32_t thisBreak = -1;
|
||||
int32_t prevWidth = fWidth;
|
||||
|
||||
fWidth = width;
|
||||
fHeight = height;
|
||||
|
||||
// don't re-break if the width hasn't changed
|
||||
if (width == prevWidth) {
|
||||
return;
|
||||
}
|
||||
|
||||
fBreakArray[0] = 0;
|
||||
fBreakCount = 1;
|
||||
|
||||
for (int32_t run = 0; run < fRunCount; run += 1) {
|
||||
int32_t glyph = fRunInfo[run].glyphBase;
|
||||
int32_t stop = fRunInfo[run + 1].glyphBase;
|
||||
int32_t dir = 1;
|
||||
|
||||
if (fRunInfo[run].rightToLeft) {
|
||||
glyph = stop - 1;
|
||||
stop = fRunInfo[run].glyphBase - 1;
|
||||
dir = -1;
|
||||
}
|
||||
|
||||
while (glyph != stop) {
|
||||
// Find the first glyph that doesn't fit on the line
|
||||
while (thisWidth + fDX[glyph] <= lineWidth) {
|
||||
thisWidth += fDX[glyph];
|
||||
glyph += dir;
|
||||
|
||||
if (glyph == stop) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check to see if we fell off the
|
||||
// end of the run
|
||||
if (glyph == stop) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Find a place before here to break,
|
||||
thisBreak = previousBreak(fCharIndices[glyph]);
|
||||
|
||||
// If there wasn't one, force one
|
||||
if (thisBreak <= fBreakArray[fBreakCount - 1]) {
|
||||
thisBreak = fCharIndices[glyph];
|
||||
}
|
||||
|
||||
// Save the break location.
|
||||
fBreakArray[fBreakCount++] = thisBreak;
|
||||
|
||||
// Reset the accumulated width
|
||||
thisWidth = 0;
|
||||
|
||||
// Map the character back to a glyph
|
||||
glyph = fGlyphIndices[thisBreak];
|
||||
|
||||
// Check to see if the new glyph is off
|
||||
// the end of the run.
|
||||
if (glyph == stop) {
|
||||
break;
|
||||
}
|
||||
|
||||
// If the glyph's not in the run we stopped in, we
|
||||
// have to re-synch to the new run
|
||||
if (glyph < fRunInfo[run].glyphBase || glyph >= fRunInfo[run + 1].glyphBase) {
|
||||
run = getGlyphRun(glyph, 0, 1);
|
||||
|
||||
if (fRunInfo[run].rightToLeft) {
|
||||
stop = fRunInfo[run].glyphBase - 1;
|
||||
dir = -1;
|
||||
} else {
|
||||
stop = fRunInfo[run + 1].glyphBase;
|
||||
dir = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the last break is after the last character
|
||||
if (fBreakArray[--fBreakCount] != fCharCount) {
|
||||
fBreakArray[++fBreakCount] = fCharCount;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t Paragraph::getGlyphRun(int32_t glyph, int32_t startingRun, int32_t direction)
|
||||
{
|
||||
int32_t limit;
|
||||
|
||||
if (direction < 0) {
|
||||
limit = -1;
|
||||
} else {
|
||||
limit = fRunCount;
|
||||
}
|
||||
|
||||
for (int32_t run = startingRun; run != limit; run += direction) {
|
||||
if (glyph >= fRunInfo[run].glyphBase && glyph < fRunInfo[run + 1].glyphBase) {
|
||||
return run;
|
||||
}
|
||||
}
|
||||
|
||||
return limit;
|
||||
}
|
||||
|
||||
int32_t Paragraph::getCharRun(int32_t ch, int32_t startingRun, int32_t direction)
|
||||
{
|
||||
int32_t limit;
|
||||
|
||||
if (direction < 0) {
|
||||
limit = -1;
|
||||
} else {
|
||||
limit = fRunCount;
|
||||
}
|
||||
|
||||
for (int32_t run = startingRun; run != limit; run += direction) {
|
||||
if (ch >= fRunInfo[run].charBase && ch < fRunInfo[run + 1].charBase) {
|
||||
return run;
|
||||
}
|
||||
}
|
||||
|
||||
return limit;
|
||||
}
|
||||
|
||||
int32_t Paragraph::getRunWidth(int32_t startGlyph, int32_t endGlyph)
|
||||
{
|
||||
int32_t width = 0;
|
||||
|
||||
for (int32_t glyph = startGlyph; glyph <= endGlyph; glyph += 1) {
|
||||
width += fDX[glyph];
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
int32_t Paragraph::drawRun(void *surface, const RenderingFontInstance *fontInstance, int32_t firstChar, int32_t lastChar,
|
||||
int32_t x, int32_t y)
|
||||
{
|
||||
int32_t firstGlyph = fGlyphIndices[firstChar];
|
||||
int32_t lastGlyph = fGlyphIndices[lastChar];
|
||||
|
||||
for (int32_t ch = firstChar; ch <= lastChar; ch += 1) {
|
||||
int32_t glyph = fGlyphIndices[ch];
|
||||
|
||||
if (glyph < firstGlyph) {
|
||||
firstGlyph = glyph;
|
||||
}
|
||||
|
||||
if (glyph > lastGlyph) {
|
||||
lastGlyph = glyph;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t dyStart = firstGlyph, dyEnd = dyStart;
|
||||
|
||||
fontInstance->setFont(surface);
|
||||
|
||||
while (dyEnd <= lastGlyph) {
|
||||
while (dyEnd <= lastGlyph && fDY[dyStart] == fDY[dyEnd]) {
|
||||
dyEnd += 1;
|
||||
}
|
||||
|
||||
fontInstance->drawGlyphs(surface, &fGlyphs[dyStart], dyEnd - dyStart,
|
||||
&fDX[dyStart], x, y + fDY[dyStart], fWidth, fHeight);
|
||||
|
||||
dyStart = dyEnd;
|
||||
}
|
||||
|
||||
return getRunWidth(firstGlyph, lastGlyph);
|
||||
}
|
||||
|
||||
void Paragraph::draw(void *surface, int32_t firstLine, int32_t lastLine)
|
||||
{
|
||||
int32_t line, x, y;
|
||||
int32_t prevRun = 0;
|
||||
|
||||
y = fAscent;
|
||||
|
||||
for (line = firstLine; line <= lastLine; line += 1) {
|
||||
int32_t firstChar = fBreakArray[line];
|
||||
int32_t lastChar = fBreakArray[line + 1] - 1;
|
||||
int32_t firstRun = getCharRun(firstChar, prevRun, 1);
|
||||
int32_t lastRun = getCharRun(lastChar, firstRun, 1);
|
||||
|
||||
x = MARGIN;
|
||||
|
||||
for (int32_t run = firstRun; run <= lastRun; run += 1) {
|
||||
const RenderingFontInstance *fontInstance = fRunInfo[run].fontInstance;
|
||||
int32_t nextBase;
|
||||
|
||||
if (run == lastRun) {
|
||||
nextBase = lastChar + 1;
|
||||
} else {
|
||||
nextBase = fRunInfo[run + 1].charBase;
|
||||
}
|
||||
|
||||
x += drawRun(surface, fontInstance, firstChar, nextBase - 1, x, y);
|
||||
firstChar = nextBase;
|
||||
}
|
||||
|
||||
y += fLineHeight;
|
||||
prevRun = lastRun;
|
||||
}
|
||||
}
|
||||
|
||||
Paragraph *Paragraph::paragraphFactory(const char *fileName, FontMap *fontMap, GUISupport *guiSupport, void *surface)
|
||||
{
|
||||
RunParams params[64];
|
||||
int32_t paramCount = 0;
|
||||
int32_t charCount = 0;
|
||||
RFIErrorCode fontStatus = RFI_NO_ERROR;
|
||||
const UChar *text = UnicodeReader::readFile(fileName, guiSupport, charCount);
|
||||
ScriptRun scriptRun(text, charCount);
|
||||
|
||||
if (text == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (scriptRun.next()) {
|
||||
int32_t start = scriptRun.getScriptStart();
|
||||
int32_t end = scriptRun.getScriptEnd();
|
||||
UScriptCode code = scriptRun.getScriptCode();
|
||||
|
||||
params[paramCount].text = &((UChar *) text)[start];
|
||||
params[paramCount].count = end - start;
|
||||
params[paramCount].scriptCode = (UScriptCode) code;
|
||||
params[paramCount].rightToLeft = false;
|
||||
|
||||
params[paramCount].fontInstance = fontMap->getScriptFont(code, fontStatus);
|
||||
|
||||
if (params[paramCount].fontInstance == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (code == USCRIPT_ARABIC) {
|
||||
params[paramCount].rightToLeft = true;
|
||||
}
|
||||
|
||||
paramCount += 1;
|
||||
}
|
||||
|
||||
return new Paragraph(surface, params, paramCount);
|
||||
}
|
||||
|
96
icu4c/source/samples/layout/paragraph.h
Normal file
96
icu4c/source/samples/layout/paragraph.h
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
*******************************************************************************
|
||||
* file name: Paragraph.h
|
||||
*
|
||||
* created on: 09/06/2000
|
||||
* created by: Eric R. Mader
|
||||
*/
|
||||
#ifndef __PARAGRAPH_H
|
||||
#define __PARAGRAPH_H
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#include "unicode/uscript.h"
|
||||
#include "unicode/brkiter.h"
|
||||
|
||||
#include "GUISupport.h"
|
||||
#include "RenderingFontInstance.h"
|
||||
#include "FontMap.h"
|
||||
|
||||
U_NAMESPACE_USE
|
||||
|
||||
#define MARGIN 10
|
||||
|
||||
struct RunParams
|
||||
{
|
||||
const RenderingFontInstance *fontInstance;
|
||||
UChar *text;
|
||||
int32_t count;
|
||||
UScriptCode scriptCode;
|
||||
UBool rightToLeft;
|
||||
};
|
||||
|
||||
struct RunInfo
|
||||
{
|
||||
const RenderingFontInstance *fontInstance;
|
||||
int32_t charBase;
|
||||
int32_t glyphBase;
|
||||
UBool rightToLeft;
|
||||
};
|
||||
|
||||
class Paragraph
|
||||
{
|
||||
public:
|
||||
Paragraph(void *surface,RunParams runs[], int32_t count);
|
||||
|
||||
~Paragraph();
|
||||
|
||||
int32_t getAscent();
|
||||
int32_t getLineHeight();
|
||||
int32_t getLineCount();
|
||||
void breakLines(int32_t width, int32_t height);
|
||||
void draw(void *surface, int32_t firstLine, int32_t lastLine);
|
||||
|
||||
static Paragraph *paragraphFactory(const char *fileName, FontMap *fontMap, GUISupport *guiSupport, void *surface);
|
||||
|
||||
protected:
|
||||
int32_t previousBreak(int32_t charIndex);
|
||||
int32_t getCharRun(int32_t ch, int32_t startingRun, int32_t direction);
|
||||
int32_t getGlyphRun(int32_t glyph, int32_t startingRun, int32_t direction);
|
||||
|
||||
int32_t getRunWidth(int32_t startGlyph, int32_t endGlyph);
|
||||
int32_t drawRun(void *surface, const RenderingFontInstance *fontInstance, int32_t firstChar, int32_t lastChar,
|
||||
int32_t x, int32_t y);
|
||||
|
||||
|
||||
private:
|
||||
int32_t fRunCount;
|
||||
RunInfo *fRunInfo;
|
||||
|
||||
int32_t fCharCount;
|
||||
UChar *fText;
|
||||
BreakIterator *fBrkiter;
|
||||
|
||||
int32_t fGlyphCount;
|
||||
LEGlyphID *fGlyphs;
|
||||
int32_t *fCharIndices;
|
||||
int32_t *fGlyphIndices;
|
||||
int32_t *fDX;
|
||||
int32_t *fDY;
|
||||
|
||||
int32_t fBreakCount;
|
||||
int32_t *fBreakArray;
|
||||
|
||||
int32_t fLineHeight;
|
||||
int32_t fAscent;
|
||||
int32_t fWidth;
|
||||
int32_t fHeight;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
123
icu4c/source/samples/layout/readme.html
Normal file
123
icu4c/source/samples/layout/readme.html
Normal file
|
@ -0,0 +1,123 @@
|
|||
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Eric Mader">
|
||||
<meta name="GENERATOR" content="Mozilla/4.72 [en] (Windows NT 5.0; U) [Netscape]">
|
||||
<title>Readme file for letest and gendata</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>
|
||||
What is the layout demo?</h2>
|
||||
The layout demo displays a paragraph of text that is laid out using the
|
||||
LayoutEngine. There are two versions of this demo, "layout.exe" which runs
|
||||
on Windows 2000, and "gnomelayout" which runs on Linux. Both programs read
|
||||
a file containing the Unicode text to display, and a file that says which
|
||||
font to use to display each script.
|
||||
<br>
|
||||
<h2>
|
||||
How do I build the layout demo?</h2>
|
||||
First, you need to build ICU, including the LayoutEngine.
|
||||
<p>On Windows, the layout project should be listed as a dependency of all,
|
||||
so layout will build when you build all. If it doesn't for some reason,
|
||||
just select the layout project in the project toolbar and build it.
|
||||
<p>On Linux systems, you need to add the "--enable-layout=yes" option when
|
||||
you invoke the runConfigureICU script. When you've done that, layout should
|
||||
build when you do "make all install"
|
||||
<p>To build the demo on Windows, just open the layout project in <icu>\source\samples\layout
|
||||
and build it. On Linux systems, connect to <top-build-dir>/samples/layout
|
||||
and do "make all"
|
||||
<br>
|
||||
<h2>
|
||||
How do I run the demo?</h2>
|
||||
Before you can run the demo, you'll need to get the fonts it uses. For
|
||||
legal reasons, we can't include these fonts with ICU, but you can get them
|
||||
for free from the web. To do this, you'll need access to a computer running
|
||||
Windows. Here's how to get the fonts:
|
||||
<p>Download the 1.3 version of the JDK from the <a href="http://www7b.boulder.ibm.com/wsdd/wspvtindex.html">IBM
|
||||
WebSphere preview technologies</a> page. From this page, follow the "Download"
|
||||
link on the right had side. You'll need to register with them if you haven't
|
||||
downloaded before. Download and install the "Runtime Environment Package."
|
||||
You'll need three fonts from this package. If you've let the installer
|
||||
use it's defaults, the fonts will be in C:\Program Files\IBM\Java13\jre\lib\fonts.
|
||||
The files you want are "Devamt.ttf" "LucidaSansRegular.ttf" and "Thonburi.ttf"
|
||||
On Windows, copy these font files to your Fonts folder, on LInux, copy
|
||||
these font files to the directory from which you'll run the layout demo.
|
||||
<p>There's still one more font to get. Go to the Microsoft <a href="http://www.microsoft.com/typography/fontpack/default.htm">TrueType
|
||||
core fonts for the Web</a> page and download the "Times New Roman" font.
|
||||
This will download an installer program, called "Times32.exe" which will
|
||||
install the Times New Roman fonts in your fonts folder. (If you've already
|
||||
got these fonts in you fonts folder, you may want to move them to another
|
||||
folder before you install these fonts.)
|
||||
<p>NOTE: this installer will display an End User License Agreement (EULA)
|
||||
which you must accept before proceeding. Be sure that you read and understand
|
||||
this agreement before you install the font.
|
||||
<p>After you run the installer program, it will add the Times Roman fonts
|
||||
to your fonts folder. If you're going to run the demo on Linux, open the
|
||||
Fonts folder and copy the "Times New Roman" font (the file name will be
|
||||
"Times.TTF") to the directory from which you'll run the demo.
|
||||
<p>That's it! Now all you have to do is run letest (CTRL+F5 in Visual C++,
|
||||
or "./gnomelayout" in Linux)
|
||||
<h2>
|
||||
How can I customize the layout demo?</h2>
|
||||
The text that the layout demo displays is read from the file "Sample.utf8."
|
||||
You can change the text by editing this file using a Unicode-aware text
|
||||
editor. (it is in UTF8 format with a BOM as the first character; the demo
|
||||
can also read UTF16 and UTF32 format files) Remember that the text will
|
||||
be displayed in a single paragraph; you can include CR and LF characters
|
||||
in the text, but they will be ignored.
|
||||
<p>If you add scripts to the text other than Arabic, Devanagari, Latin
|
||||
or Thai, you'll need to find a font which contains the characters in that
|
||||
script, and add an entry to the FontMap file ("FontMap.GDI" on Windows,
|
||||
"FontMap.Gnome" on Linux) This file contains a single entry per line. Each
|
||||
entry contains a script name followed by a colon, and then a font name.
|
||||
<p>Here is the list of legal script names:
|
||||
<blockquote><tt>ARABIC</tt>
|
||||
<br><tt>ARMENIAN</tt>
|
||||
<br><tt>BENGALI</tt>
|
||||
<br><tt>BOPOMOFO</tt>
|
||||
<br><tt>CANADIAN-ABORIGINAL</tt>
|
||||
<br><tt>CHEROKEE</tt>
|
||||
<br><tt>CYRILLIC</tt>
|
||||
<br><tt>DESERET</tt>
|
||||
<br><tt>DEVANAGARI</tt>
|
||||
<br><tt>ETHIOPIC</tt>
|
||||
<br><tt>GEORGIAN</tt>
|
||||
<br><tt>GOTHIC</tt>
|
||||
<br><tt>GREEK</tt>
|
||||
<br><tt>GUJARATI</tt>
|
||||
<br><tt>GURMUKHI</tt>
|
||||
<br><tt>HAN</tt>
|
||||
<br><tt>HANGUL</tt>
|
||||
<br><tt>HEBREW</tt>
|
||||
<br><tt>HIRAGANA</tt>
|
||||
<br><tt>KANNADA</tt>
|
||||
<br><tt>KATAKANA</tt>
|
||||
<br><tt>KHMER</tt>
|
||||
<br><tt>LATIN</tt>
|
||||
<br><tt>MALAYALAM</tt>
|
||||
<br><tt>MONGOLIAN</tt>
|
||||
<br><tt>MYANMAR</tt>
|
||||
<br><tt>OGHAM</tt>
|
||||
<br><tt>OLD-ITALIC</tt>
|
||||
<br><tt>ORIYA</tt>
|
||||
<br><tt>RUNIC</tt>
|
||||
<br><tt>SINHALA</tt>
|
||||
<br><tt>SYRIAC</tt>
|
||||
<br><tt>TAMIL</tt>
|
||||
<br><tt>TELUGU</tt>
|
||||
<br><tt>THAANA</tt>
|
||||
<br><tt>THAI</tt>
|
||||
<br><tt>TIBETAN</tt>
|
||||
<br><tt>UCAS</tt>
|
||||
<br><tt>YI</tt></blockquote>
|
||||
On Windows use the full name of the font as it appears in the Windows Fonts
|
||||
folder (eg. "Times New Roman") On Linux, use the file name of the font
|
||||
file (e.g. "Times.TTF") If you're running on Windows, you'll need to install
|
||||
the new fonts in your Fonts folder. If you're running on Linux, put them
|
||||
in the directory from which you'll run the demo.
|
||||
<br>
|
||||
<br>
|
||||
</body>
|
||||
</html>
|
67
icu4c/source/samples/layout/scrptrun.cpp
Normal file
67
icu4c/source/samples/layout/scrptrun.cpp
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
*******************************************************************************
|
||||
* file name: scrptrun.cpp
|
||||
*
|
||||
* created on: 10/17/2001
|
||||
* created by: Eric R. Mader
|
||||
*/
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#include "unicode/uscript.h"
|
||||
|
||||
#include "scrptrun.h"
|
||||
|
||||
UBool ScriptRun::sameScript(int32_t scriptOne, int32_t scriptTwo)
|
||||
{
|
||||
return scriptOne <= USCRIPT_INHERITED || scriptTwo <= USCRIPT_INHERITED || scriptOne == scriptTwo;
|
||||
}
|
||||
|
||||
UBool ScriptRun::next()
|
||||
{
|
||||
UErrorCode error = U_ZERO_ERROR;
|
||||
|
||||
if (scriptEnd >= charLimit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
scriptCode = USCRIPT_COMMON;
|
||||
|
||||
for (scriptStart = scriptEnd; scriptEnd < charLimit; scriptEnd += 1) {
|
||||
UChar high = charArray[scriptEnd];
|
||||
UChar32 ch = high;
|
||||
|
||||
if (scriptEnd < charLimit - 1 && high >= 0xD800 && high <= 0xDBFF)
|
||||
{
|
||||
UChar low = charArray[scriptEnd + 1];
|
||||
|
||||
if (low >= 0xDC00 && low <= 0xDFFF) {
|
||||
ch = (high - 0xD800) * 0x0400 + low - 0xDC00 + 0x10000;
|
||||
scriptEnd += 1;
|
||||
}
|
||||
}
|
||||
|
||||
UScriptCode sc = uscript_getScript(ch, &error);
|
||||
|
||||
if (sameScript(scriptCode, sc)) {
|
||||
if (scriptCode <= USCRIPT_INHERITED && sc > USCRIPT_INHERITED) {
|
||||
scriptCode = sc;
|
||||
}
|
||||
} else {
|
||||
// if the run broke on a surrogate pair,
|
||||
// end it before the high surrogate
|
||||
if (ch >= 0x10000) {
|
||||
scriptEnd -= 1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
116
icu4c/source/samples/layout/scrptrun.h
Normal file
116
icu4c/source/samples/layout/scrptrun.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
*******************************************************************************
|
||||
* file name: scrptrun.h
|
||||
*
|
||||
* created on: 10/17/2001
|
||||
* created by: Eric R. Mader
|
||||
*/
|
||||
|
||||
#ifndef __SCRPTRUN_H
|
||||
#define __SCRPTRUN_H
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#include "unicode/uscript.h"
|
||||
|
||||
struct ScriptRecord
|
||||
{
|
||||
UChar32 startChar;
|
||||
UChar32 endChar;
|
||||
UScriptCode scriptCode;
|
||||
};
|
||||
|
||||
class ScriptRun
|
||||
{
|
||||
public:
|
||||
ScriptRun();
|
||||
|
||||
ScriptRun(const UChar chars[], int32_t length);
|
||||
|
||||
ScriptRun(const UChar chars[], int32_t start, int32_t length);
|
||||
|
||||
void reset();
|
||||
|
||||
void reset(int32_t start, int32_t count);
|
||||
|
||||
void reset(const UChar chars[], int32_t start, int32_t length);
|
||||
|
||||
int32_t getScriptStart();
|
||||
|
||||
int32_t getScriptEnd();
|
||||
|
||||
UScriptCode getScriptCode();
|
||||
|
||||
UBool next();
|
||||
|
||||
private:
|
||||
|
||||
static UBool sameScript(int32_t scriptOne, int32_t scriptTwo);
|
||||
|
||||
int32_t charStart;
|
||||
int32_t charLimit;
|
||||
const UChar *charArray;
|
||||
|
||||
int32_t scriptStart;
|
||||
int32_t scriptEnd;
|
||||
UScriptCode scriptCode;
|
||||
};
|
||||
|
||||
inline ScriptRun::ScriptRun()
|
||||
{
|
||||
reset(NULL, 0, 0);
|
||||
}
|
||||
|
||||
inline ScriptRun::ScriptRun(const UChar chars[], int32_t length)
|
||||
{
|
||||
reset(chars, 0, length);
|
||||
}
|
||||
|
||||
inline ScriptRun::ScriptRun(const UChar chars[], int32_t start, int32_t length)
|
||||
{
|
||||
reset(chars, start, length);
|
||||
}
|
||||
|
||||
inline int32_t ScriptRun::getScriptStart()
|
||||
{
|
||||
return scriptStart;
|
||||
}
|
||||
|
||||
inline int32_t ScriptRun::getScriptEnd()
|
||||
{
|
||||
return scriptEnd;
|
||||
}
|
||||
|
||||
inline UScriptCode ScriptRun::getScriptCode()
|
||||
{
|
||||
return scriptCode;
|
||||
}
|
||||
|
||||
inline void ScriptRun::reset()
|
||||
{
|
||||
scriptStart = charStart;
|
||||
scriptEnd = charStart;
|
||||
scriptCode = USCRIPT_INVALID_CODE;
|
||||
}
|
||||
|
||||
inline void ScriptRun::reset(int32_t start, int32_t length)
|
||||
{
|
||||
charStart = start;
|
||||
charLimit = start + length;
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
inline void ScriptRun::reset(const UChar chars[], int32_t start, int32_t length)
|
||||
{
|
||||
charArray = chars;
|
||||
|
||||
reset(start, length);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
219
icu4c/source/samples/layout/sfnt.h
Normal file
219
icu4c/source/samples/layout/sfnt.h
Normal file
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
****************************************************************************** *
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
****************************************************************************** *
|
||||
* file name: sfnt.h
|
||||
*
|
||||
* created on: ??/??/2001
|
||||
* created by: Eric R. Mader
|
||||
*/
|
||||
|
||||
#ifndef __SFNT_H
|
||||
#define __SFNT_H
|
||||
|
||||
#include "LETypes.h"
|
||||
|
||||
|
||||
#ifndef ANY_NUMBER
|
||||
#define ANY_NUMBER 1
|
||||
#endif
|
||||
|
||||
struct DirectoryEntry
|
||||
{
|
||||
le_uint32 tag;
|
||||
le_uint32 checksum;
|
||||
le_uint32 offset;
|
||||
le_uint32 length;
|
||||
};
|
||||
|
||||
struct SFNTDirectory
|
||||
{
|
||||
le_uint32 scalerType;
|
||||
le_uint16 numTables;
|
||||
le_uint16 searchRange;
|
||||
le_uint16 entrySelector;
|
||||
le_uint16 rangeShift;
|
||||
DirectoryEntry tableDirectory[ANY_NUMBER];
|
||||
};
|
||||
|
||||
|
||||
struct CMAPEncodingSubtableHeader
|
||||
{
|
||||
le_uint16 platformID;
|
||||
le_uint16 platformSpecificID;
|
||||
le_uint32 encodingOffset;
|
||||
};
|
||||
|
||||
struct CMAPTable
|
||||
{
|
||||
le_uint16 version;
|
||||
le_uint16 numberSubtables;
|
||||
CMAPEncodingSubtableHeader encodingSubtableHeaders[ANY_NUMBER];
|
||||
};
|
||||
|
||||
struct CMAPEncodingSubtable
|
||||
{
|
||||
le_uint16 format;
|
||||
le_uint16 length;
|
||||
le_uint16 language;
|
||||
};
|
||||
|
||||
struct CMAPFormat0Encoding : CMAPEncodingSubtable
|
||||
{
|
||||
le_uint8 glyphIndexArray[256];
|
||||
};
|
||||
|
||||
struct CMAPFormat2Subheader
|
||||
{
|
||||
le_uint16 firstCode;
|
||||
le_uint16 entryCount;
|
||||
le_int16 idDelta;
|
||||
le_uint16 idRangeOffset;
|
||||
};
|
||||
|
||||
struct CMAPFormat2Encoding : CMAPEncodingSubtable
|
||||
{
|
||||
le_uint16 subHeadKeys[256];
|
||||
CMAPFormat2Subheader subheaders[ANY_NUMBER];
|
||||
};
|
||||
|
||||
struct CMAPFormat4Encoding : CMAPEncodingSubtable
|
||||
{
|
||||
le_uint16 segCountX2;
|
||||
le_uint16 searchRange;
|
||||
le_uint16 entrySelector;
|
||||
le_uint16 rangeShift;
|
||||
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];
|
||||
};
|
||||
|
||||
struct CMAPFormat6Encoding : CMAPEncodingSubtable
|
||||
{
|
||||
le_uint16 firstCode;
|
||||
le_uint16 entryCount;
|
||||
le_uint16 glyphIndexArray[ANY_NUMBER];
|
||||
};
|
||||
|
||||
struct CMAPEncodingSubtable32
|
||||
{
|
||||
le_uint32 format;
|
||||
le_uint32 length;
|
||||
le_uint32 language;
|
||||
};
|
||||
|
||||
struct CMAPGroup
|
||||
{
|
||||
le_uint32 startCharCode;
|
||||
le_uint32 endCharCode;
|
||||
le_uint32 startGlyphCode;
|
||||
};
|
||||
|
||||
struct CMAPFormat8Encoding : CMAPEncodingSubtable32
|
||||
{
|
||||
le_uint32 is32[65536/32];
|
||||
le_uint32 nGroups;
|
||||
CMAPGroup groups[ANY_NUMBER];
|
||||
};
|
||||
|
||||
struct CMAPFormat10Encoding : CMAPEncodingSubtable32
|
||||
{
|
||||
le_uint32 startCharCode;
|
||||
le_uint32 numCharCodes;
|
||||
le_uint16 glyphs[ANY_NUMBER];
|
||||
};
|
||||
|
||||
struct CMAPFormat12Encoding : CMAPEncodingSubtable32
|
||||
{
|
||||
le_uint32 nGroups;
|
||||
CMAPGroup groups[ANY_NUMBER];
|
||||
};
|
||||
|
||||
typedef le_int32 fixed;
|
||||
|
||||
struct BigDate
|
||||
{
|
||||
le_uint32 bc;
|
||||
le_uint32 ad;
|
||||
};
|
||||
|
||||
struct HEADTable
|
||||
{
|
||||
fixed version;
|
||||
fixed fontRevision;
|
||||
le_uint32 checksumAdjustment;
|
||||
le_uint32 magicNumber;
|
||||
le_uint16 flags;
|
||||
le_uint16 unitsPerEm;
|
||||
BigDate created;
|
||||
BigDate modified;
|
||||
le_int16 xMin;
|
||||
le_int16 yMin;
|
||||
le_int16 xMax;
|
||||
le_int16 yMax;
|
||||
le_int16 lowestRecPPEM;
|
||||
le_int16 fontDirectionHint;
|
||||
le_int16 indexToLocFormat;
|
||||
le_int16 glyphDataFormat;
|
||||
};
|
||||
|
||||
struct MAXPTable
|
||||
{
|
||||
fixed version;
|
||||
le_uint16 numGlyphs;
|
||||
le_uint16 maxPoints;
|
||||
le_uint16 maxContours;
|
||||
le_uint16 maxComponentPoints;
|
||||
le_uint16 maxComponentContours;
|
||||
le_uint16 maxZones;
|
||||
le_uint16 maxTwilightPoints;
|
||||
le_uint16 maxStorage;
|
||||
le_uint16 maxFunctionDefs;
|
||||
le_uint16 maxInstructionDefs;
|
||||
le_uint16 maxStackElements;
|
||||
le_uint16 maxSizeOfInstructions;
|
||||
le_uint16 maxComponentElements;
|
||||
le_uint16 maxComponentDepth;
|
||||
};
|
||||
|
||||
struct HHEATable
|
||||
{
|
||||
fixed version;
|
||||
le_int16 ascent;
|
||||
le_int16 descent;
|
||||
le_int16 lineGap;
|
||||
le_uint16 advanceWidthMax;
|
||||
le_int16 minLeftSideBearing;
|
||||
le_int16 minRightSideBearing;
|
||||
le_int16 xMaxExtent;
|
||||
le_int16 caretSlopeRise;
|
||||
le_int16 caretSlopeRun;
|
||||
le_int16 caretOffset;
|
||||
le_int16 reserved1;
|
||||
le_int16 reserved2;
|
||||
le_int16 reserved3;
|
||||
le_int16 reserved4;
|
||||
le_int16 metricDataFormat;
|
||||
le_uint16 numOfLongHorMetrics;
|
||||
};
|
||||
|
||||
struct LongHorMetric
|
||||
{
|
||||
le_uint16 advanceWidth;
|
||||
le_int16 leftSideBearing;
|
||||
};
|
||||
|
||||
struct HMTXTable
|
||||
{
|
||||
LongHorMetric hMetrics[ANY_NUMBER]; // ANY_NUMBER = numOfLongHorMetrics from hhea table
|
||||
// le_int16 leftSideBearing[ANY_NUMBER]; // ANY_NUMBER = numGlyphs - numOfLongHorMetrics
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Add table
Reference in a new issue