From a7571a96c307b85349eaadf0d5d9c777c7881137 Mon Sep 17 00:00:00 2001 From: Ivo Hinkelmann <ihi@openoffice.org> Date: Wed, 1 Apr 2009 11:54:14 +0000 Subject: CWS-TOOLING: integrate CWS vcl100 2009-03-26 21:27:56 +0100 pl r270106 : #i10000# fix an include path missing when using configure 2009-03-16 12:18:24 +0100 pl r269518 : #i98963# revert change 2009-03-13 14:56:47 +0100 pl r269483 : #i98980# work around a mysterious crash 2009-03-12 20:02:48 +0100 pl r269440 : resolve some warnings 2009-03-12 19:30:32 +0100 pl r269439 : resolve some warnings 2009-03-12 18:07:47 +0100 pl r269432 : solve some warnings 2009-03-12 09:07:33 +0100 hdu r269358 : #i100134# remove obsolete RCS/CVS keywords from source 2009-03-11 21:18:28 +0100 pl r269355 : #i100134# change sft.h and ttcr.h to c++ headers 2009-03-11 20:19:15 +0100 pl r269353 : #i100134# remove some ugly C style lists 2009-03-11 18:19:35 +0100 hdu r269347 : #i100134# make psprint.fontsubset source C++ and make it compile 2009-03-11 14:44:35 +0100 hdu r269334 : #i99862# fix justification of vocalized hebrew (thanks hennerdrewes) 2009-03-11 13:40:35 +0100 pl r269327 : CWS-TOOLING: rebase CWS vcl100 to trunk@269297 (milestone: DEV300:m43) 2009-03-10 16:49:34 +0100 hdu r269284 : #i1000020# add style-matching heuristics for single-char stylenames 2009-03-10 15:42:53 +0100 hdu r269278 : use fast ASCII-matching for extracting attributes from PSName 2009-03-09 16:29:08 +0100 pl r269200 : #i98980# skip bundles that are not NP plugins 2009-03-09 13:26:14 +0100 hdu r269083 : #i99868# fix text breaking for large nCharExtra 2009-03-09 12:20:01 +0100 hdu r269078 : #i99868# fix text breaking for large nCharExtra 2009-03-06 17:35:27 +0100 pl r269032 : #i98980# mouse events 2009-03-06 17:10:14 +0100 pl r269024 : #i98980# flash animations, initial paint problem 2009-03-05 20:00:21 +0100 pl r268939 : #i98980# more plugin support 2009-03-05 15:35:06 +0100 pl r268914 : #i98980# first twitches of a live plugin 2009-03-05 15:34:10 +0100 pl r268913 : #i98980# access to carbon headers 2009-03-04 15:46:29 +0100 pl r268839 : #i98980# generalize vcl SystemChildWindow from QTMovieView to NSView 2009-03-04 15:40:20 +0100 pl r268838 : #i98980# generalize vcl SystemChildWindow from QTMovieView to NSView 2009-03-04 11:30:49 +0100 hdu r268801 : #i99722# for OSX any anisotropy reported for the display resolution is best ignored 2009-03-02 15:52:21 +0100 pl r268655 : #i99770# fix ambiguous looking if statements (thanks cmc) 2009-03-02 13:28:17 +0100 pl r268649 : #i99770# fix ambiguous looking if statements (thanks cmc) 2009-02-27 15:39:30 +0100 pl r268603 : #i97512# omit degenrate current matrix 2009-02-27 12:37:29 +0100 pl r268579 : #i99716# remove unused code (thanks cmc) 2009-02-27 11:21:18 +0100 pl r268569 : #i99705 remove unused code (thanks cmc) 2009-02-23 10:42:00 +0100 pl r268345 : #i99492# remove a typo (thanks tono) 2009-02-19 12:46:21 +0100 pl r268274 : #i99411# add new mimetype 2009-02-10 12:57:59 +0100 pl r267548 : #i98980# more aqua plugin changes 2009-02-06 16:50:34 +0100 pl r267475 : #i98980# plugin detection 2009-02-06 16:46:48 +0100 pl r267474 : #i98980# make debug compilation work 2009-02-06 12:16:37 +0100 pl r267449 : #98963# add missing wrapper 2009-02-04 20:06:59 +0100 pl r267402 : #i97135# work around a gcc x64 optimizer bug 2009-02-04 13:45:36 +0100 pl r267380 : #159153# do not emit empty glyph vector 2009-02-03 17:47:16 +0100 pl r267338 : #i98533# recent gtk versions do not support GTK_MODULES for accessibility anymore 2009-02-03 10:39:46 +0100 pl r267305 : #i97146# check if the idle formatted view is still valid 2009-01-28 11:23:23 +0100 pl r267045 : #i42227# #i48965# refinement of check markings images 2009-01-27 19:40:01 +0100 pl r267016 : #i42227# #i48965# change menus wrt checkmarks and images --- vcl/source/control/ilstbox.cxx | 2 +- vcl/source/fontsubset/crc32.c | 89 - vcl/source/fontsubset/crc32.h | 46 - vcl/source/fontsubset/gsub.cxx | 12 +- vcl/source/fontsubset/gsub.h | 18 +- vcl/source/fontsubset/list.c | 9 +- vcl/source/fontsubset/makefile.mk | 4 - vcl/source/fontsubset/sft.c | 3334 ---------------------------------- vcl/source/fontsubset/sft.cxx | 3312 +++++++++++++++++++++++++++++++++ vcl/source/fontsubset/ttcr.c | 1669 ----------------- vcl/source/fontsubset/ttcr.cxx | 1669 +++++++++++++++++ vcl/source/fontsubset/ttcr.h | 280 --- vcl/source/fontsubset/ttcr.hxx | 261 +++ vcl/source/fontsubset/u2big5.inc | 5 +- vcl/source/fontsubset/u2johab.inc | 5 +- vcl/source/fontsubset/u2prc.inc | 5 +- vcl/source/fontsubset/u2shiftjis.inc | 5 +- vcl/source/fontsubset/u2wansung.inc | 5 +- vcl/source/fontsubset/xlat.c | 187 -- vcl/source/fontsubset/xlat.cxx | 188 ++ vcl/source/fontsubset/xlat.h | 68 - vcl/source/fontsubset/xlat.hxx | 54 + vcl/source/gdi/font.cxx | 4 +- vcl/source/gdi/pdfwriter_impl.cxx | 42 +- vcl/source/gdi/sallayout.cxx | 6 +- vcl/source/helper/smartid.cxx | 2 +- vcl/source/window/decoview.cxx | 13 +- vcl/source/window/dialog.cxx | 2 +- vcl/source/window/menu.cxx | 200 +- vcl/source/window/splitwin.cxx | 4 +- vcl/source/window/winproc.cxx | 6 +- 31 files changed, 5696 insertions(+), 5810 deletions(-) delete mode 100644 vcl/source/fontsubset/crc32.c delete mode 100644 vcl/source/fontsubset/crc32.h delete mode 100644 vcl/source/fontsubset/sft.c create mode 100644 vcl/source/fontsubset/sft.cxx delete mode 100644 vcl/source/fontsubset/ttcr.c create mode 100644 vcl/source/fontsubset/ttcr.cxx delete mode 100644 vcl/source/fontsubset/ttcr.h create mode 100644 vcl/source/fontsubset/ttcr.hxx delete mode 100644 vcl/source/fontsubset/xlat.c create mode 100644 vcl/source/fontsubset/xlat.cxx delete mode 100644 vcl/source/fontsubset/xlat.h create mode 100644 vcl/source/fontsubset/xlat.hxx (limited to 'vcl/source') diff --git a/vcl/source/control/ilstbox.cxx b/vcl/source/control/ilstbox.cxx index c717e491d7b2..a25ddbb68e8b 100644 --- a/vcl/source/control/ilstbox.cxx +++ b/vcl/source/control/ilstbox.cxx @@ -1124,7 +1124,7 @@ BOOL ImplListBoxWindow::SelectEntries( USHORT nSelect, LB_EVENT_TYPE eLET, BOOL mpEntryList->SetSelectionAnchor( nSelect ); } // MultiListBox nur mit CTRL/SHIFT oder nicht im SimpleMode - else if( ( !mbSimpleMode /* && !bShift */ ) || ( mbSimpleMode && ( bCtrl || bShift ) || mbStackMode ) ) + else if( ( !mbSimpleMode /* && !bShift */ ) || ( (mbSimpleMode && ( bCtrl || bShift )) || mbStackMode ) ) { // Space fuer Selektionswechsel if( !bShift && ( ( eLET == LET_KEYSPACE ) || ( eLET == LET_MBDOWN ) ) ) diff --git a/vcl/source/fontsubset/crc32.c b/vcl/source/fontsubset/crc32.c deleted file mode 100644 index 386b873a011c..000000000000 --- a/vcl/source/fontsubset/crc32.c +++ /dev/null @@ -1,89 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: crc32.c,v $ - * $Revision: 1.3 $ - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -/* $Id: crc32.c,v 1.3 2008-04-11 10:13:50 rt Exp $ */ - -/** - * - * @file crc32.c - * @brief CRC-32 calculation function - * @author Alexander Gelfenbain - */ - -#include "sft.h" -#include "crc32.h" - -static uint32 crcTable[256] = { - 0x00000000UL, 0x77073096UL, 0xEE0E612CUL, 0x990951BAUL, 0x076DC419UL, 0x706AF48FUL, 0xE963A535UL, 0x9E6495A3UL, - 0x0EDB8832UL, 0x79DCB8A4UL, 0xE0D5E91EUL, 0x97D2D988UL, 0x09B64C2BUL, 0x7EB17CBDUL, 0xE7B82D07UL, 0x90BF1D91UL, - 0x1DB71064UL, 0x6AB020F2UL, 0xF3B97148UL, 0x84BE41DEUL, 0x1ADAD47DUL, 0x6DDDE4EBUL, 0xF4D4B551UL, 0x83D385C7UL, - 0x136C9856UL, 0x646BA8C0UL, 0xFD62F97AUL, 0x8A65C9ECUL, 0x14015C4FUL, 0x63066CD9UL, 0xFA0F3D63UL, 0x8D080DF5UL, - 0x3B6E20C8UL, 0x4C69105EUL, 0xD56041E4UL, 0xA2677172UL, 0x3C03E4D1UL, 0x4B04D447UL, 0xD20D85FDUL, 0xA50AB56BUL, - 0x35B5A8FAUL, 0x42B2986CUL, 0xDBBBC9D6UL, 0xACBCF940UL, 0x32D86CE3UL, 0x45DF5C75UL, 0xDCD60DCFUL, 0xABD13D59UL, - 0x26D930ACUL, 0x51DE003AUL, 0xC8D75180UL, 0xBFD06116UL, 0x21B4F4B5UL, 0x56B3C423UL, 0xCFBA9599UL, 0xB8BDA50FUL, - 0x2802B89EUL, 0x5F058808UL, 0xC60CD9B2UL, 0xB10BE924UL, 0x2F6F7C87UL, 0x58684C11UL, 0xC1611DABUL, 0xB6662D3DUL, - 0x76DC4190UL, 0x01DB7106UL, 0x98D220BCUL, 0xEFD5102AUL, 0x71B18589UL, 0x06B6B51FUL, 0x9FBFE4A5UL, 0xE8B8D433UL, - 0x7807C9A2UL, 0x0F00F934UL, 0x9609A88EUL, 0xE10E9818UL, 0x7F6A0DBBUL, 0x086D3D2DUL, 0x91646C97UL, 0xE6635C01UL, - 0x6B6B51F4UL, 0x1C6C6162UL, 0x856530D8UL, 0xF262004EUL, 0x6C0695EDUL, 0x1B01A57BUL, 0x8208F4C1UL, 0xF50FC457UL, - 0x65B0D9C6UL, 0x12B7E950UL, 0x8BBEB8EAUL, 0xFCB9887CUL, 0x62DD1DDFUL, 0x15DA2D49UL, 0x8CD37CF3UL, 0xFBD44C65UL, - 0x4DB26158UL, 0x3AB551CEUL, 0xA3BC0074UL, 0xD4BB30E2UL, 0x4ADFA541UL, 0x3DD895D7UL, 0xA4D1C46DUL, 0xD3D6F4FBUL, - 0x4369E96AUL, 0x346ED9FCUL, 0xAD678846UL, 0xDA60B8D0UL, 0x44042D73UL, 0x33031DE5UL, 0xAA0A4C5FUL, 0xDD0D7CC9UL, - 0x5005713CUL, 0x270241AAUL, 0xBE0B1010UL, 0xC90C2086UL, 0x5768B525UL, 0x206F85B3UL, 0xB966D409UL, 0xCE61E49FUL, - 0x5EDEF90EUL, 0x29D9C998UL, 0xB0D09822UL, 0xC7D7A8B4UL, 0x59B33D17UL, 0x2EB40D81UL, 0xB7BD5C3BUL, 0xC0BA6CADUL, - 0xEDB88320UL, 0x9ABFB3B6UL, 0x03B6E20CUL, 0x74B1D29AUL, 0xEAD54739UL, 0x9DD277AFUL, 0x04DB2615UL, 0x73DC1683UL, - 0xE3630B12UL, 0x94643B84UL, 0x0D6D6A3EUL, 0x7A6A5AA8UL, 0xE40ECF0BUL, 0x9309FF9DUL, 0x0A00AE27UL, 0x7D079EB1UL, - 0xF00F9344UL, 0x8708A3D2UL, 0x1E01F268UL, 0x6906C2FEUL, 0xF762575DUL, 0x806567CBUL, 0x196C3671UL, 0x6E6B06E7UL, - 0xFED41B76UL, 0x89D32BE0UL, 0x10DA7A5AUL, 0x67DD4ACCUL, 0xF9B9DF6FUL, 0x8EBEEFF9UL, 0x17B7BE43UL, 0x60B08ED5UL, - 0xD6D6A3E8UL, 0xA1D1937EUL, 0x38D8C2C4UL, 0x4FDFF252UL, 0xD1BB67F1UL, 0xA6BC5767UL, 0x3FB506DDUL, 0x48B2364BUL, - 0xD80D2BDAUL, 0xAF0A1B4CUL, 0x36034AF6UL, 0x41047A60UL, 0xDF60EFC3UL, 0xA867DF55UL, 0x316E8EEFUL, 0x4669BE79UL, - 0xCB61B38CUL, 0xBC66831AUL, 0x256FD2A0UL, 0x5268E236UL, 0xCC0C7795UL, 0xBB0B4703UL, 0x220216B9UL, 0x5505262FUL, - 0xC5BA3BBEUL, 0xB2BD0B28UL, 0x2BB45A92UL, 0x5CB36A04UL, 0xC2D7FFA7UL, 0xB5D0CF31UL, 0x2CD99E8BUL, 0x5BDEAE1DUL, - 0x9B64C2B0UL, 0xEC63F226UL, 0x756AA39CUL, 0x026D930AUL, 0x9C0906A9UL, 0xEB0E363FUL, 0x72076785UL, 0x05005713UL, - 0x95BF4A82UL, 0xE2B87A14UL, 0x7BB12BAEUL, 0x0CB61B38UL, 0x92D28E9BUL, 0xE5D5BE0DUL, 0x7CDCEFB7UL, 0x0BDBDF21UL, - 0x86D3D2D4UL, 0xF1D4E242UL, 0x68DDB3F8UL, 0x1FDA836EUL, 0x81BE16CDUL, 0xF6B9265BUL, 0x6FB077E1UL, 0x18B74777UL, - 0x88085AE6UL, 0xFF0F6A70UL, 0x66063BCAUL, 0x11010B5CUL, 0x8F659EFFUL, 0xF862AE69UL, 0x616BFFD3UL, 0x166CCF45UL, - 0xA00AE278UL, 0xD70DD2EEUL, 0x4E048354UL, 0x3903B3C2UL, 0xA7672661UL, 0xD06016F7UL, 0x4969474DUL, 0x3E6E77DBUL, - 0xAED16A4AUL, 0xD9D65ADCUL, 0x40DF0B66UL, 0x37D83BF0UL, 0xA9BCAE53UL, 0xDEBB9EC5UL, 0x47B2CF7FUL, 0x30B5FFE9UL, - 0xBDBDF21CUL, 0xCABAC28AUL, 0x53B39330UL, 0x24B4A3A6UL, 0xBAD03605UL, 0xCDD70693UL, 0x54DE5729UL, 0x23D967BFUL, - 0xB3667A2EUL, 0xC4614AB8UL, 0x5D681B02UL, 0x2A6F2B94UL, 0xB40BBE37UL, 0xC30C8EA1UL, 0x5A05DF1BUL, 0x2D02EF8DUL -}; - -uint32 crc32(const void *ptr, size_t len) -{ - uint32 crc = 0xFFFFFFFF; - const byte *bp = (const byte *) ptr; - size_t i; - - for (i=0; i<len; i++) { - crc = crcTable[(crc ^ bp[i]) & 0xFF] ^ (crc >> 8); - } - - return crc ^ 0xFFFFFFFF; -} diff --git a/vcl/source/fontsubset/crc32.h b/vcl/source/fontsubset/crc32.h deleted file mode 100644 index fa9ef71a1432..000000000000 --- a/vcl/source/fontsubset/crc32.h +++ /dev/null @@ -1,46 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: crc32.h,v $ - * $Revision: 1.4 $ - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -/* $Id: crc32.h,v 1.4 2008-04-11 10:14:08 rt Exp $ */ - -/** - * - * @file crc32.h - * @brief CRC-32 calculation function - * @author Alexander Gelfenbain - */ - -#ifdef __cplusplus -extern "C"{ -#endif - sal_Int32 crc32(const void *ptr, sal_Int32 len); -#ifdef __cplusplus -} -#endif diff --git a/vcl/source/fontsubset/gsub.cxx b/vcl/source/fontsubset/gsub.cxx index e73ccccc12a4..9715e7fc8585 100644 --- a/vcl/source/fontsubset/gsub.cxx +++ b/vcl/source/fontsubset/gsub.cxx @@ -6,9 +6,6 @@ * * OpenOffice.org - a multi-platform office productivity suite * - * $RCSfile: gsub.cxx,v $ - * $Revision: 1.12.18.1 $ - * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify @@ -31,9 +28,7 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_vcl.hxx" -#include "sft.h" -#undef true -#undef false +#include "sft.hxx" #include "gsub.h" @@ -41,6 +36,9 @@ #include <map> #include <algorithm> +namespace vcl +{ + typedef sal_uInt32 ULONG; typedef sal_uInt16 USHORT; typedef sal_uInt8 FT_Byte; @@ -355,3 +353,5 @@ int HasVerticalGSUB( struct _TrueTypeFont* pTTFile ) GlyphSubstitution* pGlyphSubstitution = (GlyphSubstitution*)pTTFile->pGSubstitution; return pGlyphSubstitution ? +1 : 0; } + +} diff --git a/vcl/source/fontsubset/gsub.h b/vcl/source/fontsubset/gsub.h index c64b2abb7e00..58b5b69c3e25 100644 --- a/vcl/source/fontsubset/gsub.h +++ b/vcl/source/fontsubset/gsub.h @@ -6,9 +6,6 @@ * * OpenOffice.org - a multi-platform office productivity suite * - * $RCSfile: gsub.h,v $ - * $Revision: 1.6.18.1 $ - * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify @@ -31,20 +28,17 @@ #ifndef _PSP_GSUB_H #define _PSP_GSUB_H -#ifdef __cplusplus -extern "C" { -#endif +namespace vcl +{ -int HasVerticalGSUB( struct _TrueTypeFont* pTTFile ); +int HasVerticalGSUB( struct vcl::_TrueTypeFont* pTTFile ); -int UseGSUB( struct _TrueTypeFont* pTTFile, int nGlyph, int wmode ); +int UseGSUB( struct vcl::_TrueTypeFont* pTTFile, int nGlyph, int wmode ); -int ReadGSUB( struct _TrueTypeFont* pTTFile, int nRequestedScript, int nRequestedLangsys ); +int ReadGSUB( struct vcl::_TrueTypeFont* pTTFile, int nRequestedScript, int nRequestedLangsys ); -void ReleaseGSUB( struct _TrueTypeFont* pTTFile ); +void ReleaseGSUB( struct vcl::_TrueTypeFont* pTTFile ); -#ifdef __cplusplus } -#endif #endif /* _PSP_GSUB_H */ diff --git a/vcl/source/fontsubset/list.c b/vcl/source/fontsubset/list.c index 83ebe8595a46..86864650db85 100644 --- a/vcl/source/fontsubset/list.c +++ b/vcl/source/fontsubset/list.c @@ -6,9 +6,6 @@ * * OpenOffice.org - a multi-platform office productivity suite * - * $RCSfile: list.c,v $ - * $Revision: 1.8 $ - * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify @@ -28,8 +25,6 @@ * ************************************************************************/ -/* $Id: list.c,v 1.8 2008-06-25 14:19:44 kz Exp $ */ - /*[]---------------------------------------------------[]*/ /*| |*/ /*| list.c - bidirectional list class |*/ @@ -67,7 +62,7 @@ typedef struct _lnode { struct _list { lnode *head, *tail, *cptr; size_t aCount; - void (*eDtor)(void *); + list_destructor eDtor; }; /*- private methods */ @@ -177,7 +172,7 @@ void listDispose(list this) /*- dtor */ free(this); } -void listSetElementDtor(list this, void (*f)(void *)) +void listSetElementDtor(list this, list_destructor f) { assert(this != 0); this->eDtor = f; diff --git a/vcl/source/fontsubset/makefile.mk b/vcl/source/fontsubset/makefile.mk index b1d2552752a8..b7d719f3c912 100644 --- a/vcl/source/fontsubset/makefile.mk +++ b/vcl/source/fontsubset/makefile.mk @@ -6,10 +6,6 @@ # # OpenOffice.org - a multi-platform office productivity suite # -# $RCSfile: makefile.mk,v $ -# -# $Revision: 1.6 $ -# # This file is part of OpenOffice.org. # # OpenOffice.org is free software: you can redistribute it and/or modify diff --git a/vcl/source/fontsubset/sft.c b/vcl/source/fontsubset/sft.c deleted file mode 100644 index be54a872fd7f..000000000000 --- a/vcl/source/fontsubset/sft.c +++ /dev/null @@ -1,3334 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: sft.c,v $ - * $Revision: 1.47.4.1 $ - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -/* - * Sun Font Tools - * - * Author: Alexander Gelfenbain - * - */ - -#if OSL_DEBUG_LEVEL == 0 -# ifndef NDEBUG -# define NDEBUG -# endif -#endif -#include <assert.h> - -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#ifdef UNX -#include <sys/mman.h> -#include <sys/stat.h> -#endif -#include "sft.h" -#include "gsub.h" -#if ! (defined(NO_TTCR) && defined(NO_TYPE42)) -#include "ttcr.h" -#endif -#ifdef NO_LIST -#include "list.h" /* list.h does not get included in the sft.h */ -#endif -#ifndef NO_MAPPERS /* include MapChar() and MapString() */ -#include "xlat.h" -#endif -#ifndef NO_TYPE3 /* include CreateT3FromTTGlyphs() */ -#include <rtl/crc.h> -#endif - -#include <osl/endian.h> - -#ifdef TEST7 -#include <ctype.h> -#endif - -/*- module identification */ - -const char *modname = "SunTypeTools-TT"; -const char *modver = "1.0"; -const char *modextra = "gelf"; - -/*- private functions, constants and data types */ /*FOLD00*/ - -enum PathSegmentType { - PS_NOOP = 0, - PS_MOVETO = 1, - PS_LINETO = 2, - PS_CURVETO = 3, - PS_CLOSEPATH = 4 -}; - -typedef struct { - int type; - int x1, y1; - int x2, y2; - int x3, y3; -} PSPathElement; - -/*- In horisontal writing mode right sidebearing is calculated using this formula - *- rsb = aw - (lsb + xMax - xMin) -*/ -typedef struct { - sal_Int16 xMin; - sal_Int16 yMin; - sal_Int16 xMax; - sal_Int16 yMax; - sal_uInt16 aw; /*- Advance Width (horisontal writing mode) */ - sal_Int16 lsb; /*- Left sidebearing (horisontal writing mode) */ - sal_uInt16 ah; /*- advance height (vertical writing mode) */ - sal_Int16 tsb; /*- top sidebearing (vertical writing mode) */ -} TTGlyphMetrics; - -#define HFORMAT_LINELEN 64 - -typedef struct { - FILE *o; - char buffer[HFORMAT_LINELEN]; - int bufpos; - int total; -} HexFmt; - -typedef struct { - sal_uInt32 nGlyphs; /* number of glyphs in the font + 1 */ - sal_uInt32 *offs; /* array of nGlyphs offsets */ -} GlyphOffsets; - -/* private tags */ -static const sal_uInt32 TTFontClassTag = 0x74746663; /* 'ttfc' */ - -static const sal_uInt32 T_true = 0x74727565; /* 'true' */ -static const sal_uInt32 T_ttcf = 0x74746366; /* 'ttcf' */ - -/* standard TrueType table tags */ -#define T_maxp 0x6D617870 -#define T_glyf 0x676C7966 -#define T_head 0x68656164 -#define T_loca 0x6C6F6361 -#define T_name 0x6E616D65 -#define T_hhea 0x68686561 -#define T_hmtx 0x686D7478 -#define T_cmap 0x636D6170 -#define T_vhea 0x76686561 -#define T_vmtx 0x766D7478 -#define T_OS2 0x4F532F32 -#define T_post 0x706F7374 -#define T_kern 0x6B65726E -#define T_cvt 0x63767420 -#define T_prep 0x70726570 -#define T_fpgm 0x6670676D -#define T_gsub 0x47535542 - -#define LAST_URANGE_BIT 69 -const char *ulcodes[LAST_URANGE_BIT+2] = { - /* 0 */ "Basic Latin", - /* 1 */ "Latin-1 Supplement", - /* 2 */ "Latin Extended-A", - /* 3 */ "Latin Extended-B", - /* 4 */ "IPA Extensions", - /* 5 */ "Spacing Modifier Letters", - /* 6 */ "Combining Diacritical Marks", - /* 7 */ "Basic Greek", - /* 8 */ "Greek Symbols And Coptic", - /* 9 */ "Cyrillic", - /* 10 */ "Armenian", - /* 11 */ "Basic Hebrew", - /* 12 */ "Hebrew Extended (A and B blocks combined)", - /* 13 */ "Basic Arabic", - /* 14 */ "Arabic Extended", - /* 15 */ "Devanagari", - /* 16 */ "Bengali", - /* 17 */ "Gurmukhi", - /* 18 */ "Gujarati", - /* 19 */ "Oriya", - /* 20 */ "Tamil", - /* 21 */ "Telugu", - /* 22 */ "Kannada", - /* 23 */ "Malayalam", - /* 24 */ "Thai", - /* 25 */ "Lao", - /* 26 */ "Basic Georgian", - /* 27 */ "Georgian Extended", - /* 28 */ "Hangul Jamo", - /* 29 */ "Latin Extended Additional", - /* 30 */ "Greek Extended", - /* 31 */ "General Punctuation", - /* 32 */ "Superscripts And Subscripts", - /* 33 */ "Currency Symbols", - /* 34 */ "Combining Diacritical Marks For Symbols", - /* 35 */ "Letterlike Symbols", - /* 36 */ "Number Forms", - /* 37 */ "Arrows", - /* 38 */ "Mathematical Operators", - /* 39 */ "Miscellaneous Technical", - /* 40 */ "Control Pictures", - /* 41 */ "Optical Character Recognition", - /* 42 */ "Enclosed Alphanumerics", - /* 43 */ "Box Drawing", - /* 44 */ "Block Elements", - /* 45 */ "Geometric Shapes", - /* 46 */ "Miscellaneous Symbols", - /* 47 */ "Dingbats", - /* 48 */ "CJK Symbols And Punctuation", - /* 49 */ "Hiragana", - /* 50 */ "Katakana", - /* 51 */ "Bopomofo", - /* 52 */ "Hangul Compatibility Jamo", - /* 53 */ "CJK Miscellaneous", - /* 54 */ "Enclosed CJK Letters And Months", - /* 55 */ "CJK Compatibility", - /* 56 */ "Hangul", - /* 57 */ "Reserved for Unicode SubRanges", - /* 58 */ "Reserved for Unicode SubRanges", - /* 59 */ "CJK Unified Ideographs", - /* 60 */ "Private Use Area", - /* 61 */ "CJK Compatibility Ideographs", - /* 62 */ "Alphabetic Presentation Forms", - /* 63 */ "Arabic Presentation Forms-A", - /* 64 */ "Combining Half Marks", - /* 65 */ "CJK Compatibility Forms", - /* 66 */ "Small Form Variants", - /* 67 */ "Arabic Presentation Forms-B", - /* 68 */ "Halfwidth And Fullwidth Forms", - /* 69 */ "Specials", - /*70-127*/ "Reserved for Unicode SubRanges" -}; - - - -/*- inline functions */ /*FOLD01*/ -#ifdef __GNUC__ -#define _inline static __inline__ -#else -#define _inline static -#endif - -_inline void *smalloc(size_t size) -{ - void *res = malloc(size); - assert(res != 0); - return res; -} - -_inline void *scalloc(size_t n, size_t size) -{ - void *res = calloc(n, size); - assert(res != 0); - return res; -} - -_inline sal_uInt32 mkTag(sal_uInt8 a, sal_uInt8 b, sal_uInt8 c, sal_uInt8 d) { - return (a << 24) | (b << 16) | (c << 8) | d; -} - -/*- Data access macros for data stored in big-endian or little-endian format */ -_inline sal_Int16 GetInt16(const sal_uInt8 *ptr, size_t offset, int bigendian) -{ - sal_Int16 t; - assert(ptr != 0); - - if (bigendian) { - t = (ptr+offset)[0] << 8 | (ptr+offset)[1]; - } else { - t = (ptr+offset)[1] << 8 | (ptr+offset)[0]; - } - - return t; -} - -_inline sal_uInt16 GetUInt16(const sal_uInt8 *ptr, size_t offset, int bigendian) -{ - sal_uInt16 t; - assert(ptr != 0); - - if (bigendian) { - t = (ptr+offset)[0] << 8 | (ptr+offset)[1]; - } else { - t = (ptr+offset)[1] << 8 | (ptr+offset)[0]; - } - - return t; -} - -_inline sal_Int32 GetInt32(const sal_uInt8 *ptr, size_t offset, int bigendian) -{ - sal_Int32 t; - assert(ptr != 0); - - if (bigendian) { - t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 | - (ptr+offset)[2] << 8 | (ptr+offset)[3]; - } else { - t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 | - (ptr+offset)[1] << 8 | (ptr+offset)[0]; - } - - return t; -} - -_inline sal_uInt32 GetUInt32(const sal_uInt8 *ptr, size_t offset, int bigendian) -{ - sal_uInt32 t; - assert(ptr != 0); - - - if (bigendian) { - t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 | - (ptr+offset)[2] << 8 | (ptr+offset)[3]; - } else { - t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 | - (ptr+offset)[1] << 8 | (ptr+offset)[0]; - } - - return t; -} - -_inline void PutInt16(sal_Int16 val, sal_uInt8 *ptr, size_t offset, int bigendian) -{ - assert(ptr != 0); - - if (bigendian) { - ptr[offset] = (sal_uInt8)((val >> 8) & 0xFF); - ptr[offset+1] = (sal_uInt8)(val & 0xFF); - } else { - ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF); - ptr[offset] = (sal_uInt8)(val & 0xFF); - } - -} - -#if defined(OSL_BIG_ENDIAN) -#define Int16FromMOTA(a) (a) -#define Int32FromMOTA(a) (a) -#else -static sal_uInt16 Int16FromMOTA(sal_uInt16 a) { - return (sal_uInt16) (((sal_uInt8)((a) >> 8)) | ((sal_uInt8)(a) << 8)); -} -static sal_uInt32 Int32FromMOTA(sal_uInt32 a) { - return ((a>>24)&0xFF) | (((a>>8)&0xFF00) | ((a&0xFF00)<<8) | ((a&0xFF)<<24)); -} -#endif - -_inline F16Dot16 fixedMul(F16Dot16 a, F16Dot16 b) -{ - unsigned int a1, b1; - unsigned int a2, b2; - F16Dot16 res; - int sign; - - sign = (a & 0x80000000) ^ (b & 0x80000000); - if (a < 0) a = -a; - if (b < 0) b = -b; - - a1 = a >> 16; - b1 = a & 0xFFFF; - a2 = b >> 16; - b2 = b & 0xFFFF; - - res = a1 * a2; - - /* if (res > 0x7FFF) assert(!"fixedMul: F16Dot16 overflow"); */ - - res <<= 16; - res += a1 * b2 + b1 * a2 + ((b1 * b2) >> 16); - - return sign ? -res : res; -} - - -_inline F16Dot16 fixedDiv(F16Dot16 a, F16Dot16 b) -{ - unsigned int f, r; - F16Dot16 res; - int sign; - - sign = (a & 0x80000000) ^ (b & 0x80000000); - if (a < 0) a = -a; - if (b < 0) b = -b; - - f = a / b; - r = a % b; - - /* if (f > 0x7FFFF) assert(!"fixedDiv: F16Dot16 overflow"); */ - - while (r > 0xFFFF) { - r >>= 1; - b >>= 1; - } - - res = (f << 16) + (r << 16) / b; - - return sign ? -res : res; -} - -/*- returns a * b / c -*/ -/* XXX provide a real implementation that preserves accuracy */ -_inline F16Dot16 fixedMulDiv(F16Dot16 a, F16Dot16 b, F16Dot16 c) -{ - F16Dot16 res; - - res = fixedMul(a, b); - return fixedDiv(res, c); -} - -/*- Translate units from TT to PS (standard 1/1000) -*/ -_inline int XUnits(int unitsPerEm, int n) -{ - return (n * 1000) / unitsPerEm; -} - -_inline const char *UnicodeRangeName(sal_uInt16 bit) -{ - if (bit > LAST_URANGE_BIT) bit = LAST_URANGE_BIT+1; - - return ulcodes[bit]; -} - -_inline sal_uInt8 *getTable(TrueTypeFont *ttf, sal_uInt32 ord) -{ - return ttf->tables[ord]; -} - -_inline sal_uInt32 getTableSize(TrueTypeFont *ttf, sal_uInt32 ord) -{ - return ttf->tlens[ord]; -} - -#ifndef NO_TYPE42 -/* Hex Formatter functions */ -static char HexChars[] = "0123456789ABCDEF"; - -static HexFmt *HexFmtNew(FILE *outf) -{ - HexFmt *res = smalloc(sizeof(HexFmt)); - res->bufpos = res->total = 0; - res->o = outf; - return res; -} - -static void HexFmtFlush(HexFmt *_this) -{ - if (_this->bufpos) { - fwrite(_this->buffer, 1, _this->bufpos, _this->o); - _this->bufpos = 0; - } -} - - -_inline void HexFmtOpenString(HexFmt *_this) -{ - fputs("<\n", _this->o); -} - -_inline void HexFmtCloseString(HexFmt *_this) -{ - HexFmtFlush(_this); - fputs("00\n>\n", _this->o); -} - -_inline void HexFmtDispose(HexFmt *_this) -{ - HexFmtFlush(_this); - free(_this); -} - -static void HexFmtBlockWrite(HexFmt *_this, const void *ptr, sal_uInt32 size) -{ - sal_uInt8 Ch; - sal_uInt32 i; - - if (_this->total + size > 65534) { - HexFmtFlush(_this); - HexFmtCloseString(_this); - _this->total = 0; - HexFmtOpenString(_this); - } - for (i=0; i<size; i++) { - Ch = ((sal_uInt8 *) ptr)[i]; - _this->buffer[_this->bufpos++] = HexChars[Ch >> 4]; - _this->buffer[_this->bufpos++] = HexChars[Ch & 0xF]; - if (_this->bufpos == HFORMAT_LINELEN) { - HexFmtFlush(_this); - fputc('\n', _this->o); - } - - } - _this->total += size; -} -#endif - - - -/* Outline Extraction functions */ /*FOLD01*/ - -/* fills the aw and lsb entries of the TTGlyphMetrics structure from hmtx table -*/ -static void GetMetrics(TrueTypeFont *ttf, sal_uInt32 glyphID, TTGlyphMetrics *metrics) -{ - sal_uInt8 *table = getTable(ttf, O_hmtx); - - metrics->aw = metrics->lsb = metrics->ah = metrics->tsb = 0; - if (!table || !ttf->numberOfHMetrics) return; - - if (glyphID < ttf->numberOfHMetrics) { - metrics->aw = GetUInt16(table, 4 * glyphID, 1); - metrics->lsb = GetInt16(table, 4 * glyphID + 2, 1); - } else { - metrics->aw = GetUInt16(table, 4 * (ttf->numberOfHMetrics - 1), 1); - metrics->lsb = GetInt16(table + ttf->numberOfHMetrics * 4, (glyphID - ttf->numberOfHMetrics) * 2, 1); - } - - table = getTable(ttf, O_vmtx); - if (!table || !ttf->numOfLongVerMetrics) return; - - if (glyphID < ttf->numOfLongVerMetrics) { - metrics->ah = GetUInt16(table, 4 * glyphID, 1); - metrics->tsb = GetInt16(table, 4 * glyphID + 2, 1); - } else { - metrics->ah = GetUInt16(table, 4 * (ttf->numOfLongVerMetrics - 1), 1); - metrics->tsb = GetInt16(table + ttf->numOfLongVerMetrics * 4, (glyphID - ttf->numOfLongVerMetrics) * 2, 1); - } -} - -static int GetTTGlyphOutline(TrueTypeFont *, sal_uInt32 , ControlPoint **, TTGlyphMetrics *, list ); - -/* returns the number of control points, allocates the pointArray */ -static int GetSimpleTTOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics) /*FOLD02*/ -{ - sal_uInt8 *table = getTable(ttf, O_glyf); - sal_uInt8 *ptr, *p, flag, n; - sal_Int16 numberOfContours; - sal_uInt16 t, instLen, lastPoint=0; - int i, j, z; - ControlPoint* pa; - - *pointArray = 0; - - /* printf("GetSimpleTTOutline(%d)\n", glyphID); */ - - if (glyphID >= ttf->nglyphs) return 0; /*- glyph is not present in the font */ - ptr = table + ttf->goffsets[glyphID]; - if ((numberOfContours = GetInt16(ptr, 0, 1)) <= 0) return 0; /*- glyph is not simple */ - - if (metrics) { /*- GetCompoundTTOutline() calls this function with NULL metrics -*/ - metrics->xMin = GetInt16(ptr, 2, 1); - metrics->yMin = GetInt16(ptr, 4, 1); - metrics->xMax = GetInt16(ptr, 6, 1); - metrics->yMax = GetInt16(ptr, 8, 1); - GetMetrics(ttf, glyphID, metrics); - } - - /* determine the last point and be extra safe about it. But probably this code is not needed */ - - for (i=0; i<numberOfContours; i++) { - if ((t = GetUInt16(ptr, 10+i*2, 1)) > lastPoint) lastPoint = t; - } - - instLen = GetUInt16(ptr, 10 + numberOfContours*2, 1); - p = ptr + 10 + 2 * numberOfContours + 2 + instLen; - pa = calloc(lastPoint+1, sizeof(ControlPoint)); - - i = 0; - while (i <= lastPoint) { - pa[i++].flags = (sal_uInt32) (flag = *p++); - if (flag & 8) { /*- repeat flag */ - n = *p++; - for (j=0; j<n; j++) { - if (i > lastPoint) { /*- if the font is really broken */ - free(pa); - return 0; - } - pa[i++].flags = flag; - } - } - } - - /*- Process the X coordinate */ - z = 0; - for (i = 0; i <= lastPoint; i++) { - if (pa[i].flags & 0x02) { - if (pa[i].flags & 0x10) { - z += (int) (*p++); - } else { - z -= (int) (*p++); - } - } else if ( !(pa[i].flags & 0x10)) { - z += GetInt16(p, 0, 1); - p += 2; - } - pa[i].x = (sal_Int16)z; - } - - /*- Process the Y coordinate */ - z = 0; - for (i = 0; i <= lastPoint; i++) { - if (pa[i].flags & 0x04) { - if (pa[i].flags & 0x20) { - z += *p++; - } else { - z -= *p++; - } - } else if ( !(pa[i].flags & 0x20)) { - z += GetInt16(p, 0, 1); - p += 2; - } - pa[i].y = (sal_Int16)z; - } - - for (i=0; i<numberOfContours; i++) { - pa[GetUInt16(ptr, 10 + i * 2, 1)].flags |= 0x00008000; /*- set the end contour flag */ - } - - *pointArray = pa; - return lastPoint + 1; -} - -static int GetCompoundTTOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, list glyphlist) /*FOLD02*/ -{ - sal_uInt16 flags, index; - sal_Int16 e, f, numberOfContours; - sal_uInt8 *table = getTable(ttf, O_glyf); - sal_uInt8 *ptr; - list myPoints; - ControlPoint *nextComponent, *pa; - int i, np; - F16Dot16 a = 0x10000, b = 0, c = 0, d = 0x10000, m, n, abs1, abs2, abs3; - - *pointArray = 0; - /* printf("GetCompoundTTOutline(%d)\n", glyphID); */ - - if (glyphID >= ttf->nglyphs) { /*- incorrect glyphID */ - return 0; - } - ptr = table + ttf->goffsets[glyphID]; - if ((numberOfContours = GetInt16(ptr, 0, 1)) != -1) { /*- glyph is not compound */ - return 0; - } - - myPoints = listNewEmpty(); - listSetElementDtor(myPoints, free); - - if (metrics) { - metrics->xMin = GetInt16(ptr, 2, 1); - metrics->yMin = GetInt16(ptr, 4, 1); - metrics->xMax = GetInt16(ptr, 6, 1); - metrics->yMax = GetInt16(ptr, 8, 1); - GetMetrics(ttf, glyphID, metrics); - } - - ptr += 10; - - do { - flags = GetUInt16(ptr, 0, 1); - /* printf("flags: 0x%X\n", flags); */ - index = GetUInt16(ptr, 2, 1); - ptr += 4; - - if (listFind(glyphlist, (void *) (sal_IntPtr) index)) { -#if OSL_DEBUG_LEVEL > 1 - fprintf(stderr, "Endless loop found in a compound glyph.\n"); - fprintf(stderr, "%d -> ", index); - listToFirst(glyphlist); - fprintf(stderr," ["); - do { - fprintf(stderr,"%d ", (int) listCurrent(glyphlist)); - } while (listNext(glyphlist)); - fprintf(stderr,"]\n"); - /**/ -#endif - } - - listAppend(glyphlist, (void *) (sal_IntPtr) index); - -#ifdef DEBUG2 - fprintf(stderr,"glyphlist: += %d\n", index); -#endif - - if ((np = GetTTGlyphOutline(ttf, index, &nextComponent, 0, glyphlist)) == 0) { - /* XXX that probably indicates a corrupted font */ -#if OSL_DEBUG_LEVEL > 1 - fprintf(stderr, "An empty compound!\n"); - /* assert(!"An empty compound"); */ -#endif - } - - listToLast(glyphlist); -#ifdef DEBUG2 - listToFirst(glyphlist); - fprintf(stderr,"%d [", listCount(glyphlist)); - if (!listIsEmpty(glyphlist)) { - do { - fprintf(stderr,"%d ", (int) listCurrent(glyphlist)); - } while (listNext(glyphlist)); - } - fprintf(stderr, "]\n"); - fprintf(stderr, "glyphlist: -= %d\n", (int) listCurrent(glyphlist)); - -#endif - listRemove(glyphlist); - - if (flags & USE_MY_METRICS) { - if (metrics) GetMetrics(ttf, index, metrics); - } - - if (flags & ARG_1_AND_2_ARE_WORDS) { - e = GetInt16(ptr, 0, 1); - f = GetInt16(ptr, 2, 1); - /* printf("ARG_1_AND_2_ARE_WORDS: %d %d\n", e & 0xFFFF, f & 0xFFFF); */ - ptr += 4; - } else { - if (flags & ARGS_ARE_XY_VALUES) { /* args are signed */ - e = (sal_Int8) *ptr++; - f = (sal_Int8) *ptr++; - /* printf("ARGS_ARE_XY_VALUES: %d %d\n", e & 0xFF, f & 0xFF); */ - } else { /* args are unsigned */ - /* printf("!ARGS_ARE_XY_VALUES\n"); */ - e = *ptr++; - f = *ptr++; - } - - } - - a = d = 0x10000; - b = c = 0; - - if (flags & WE_HAVE_A_SCALE) { -#ifdef DEBUG2 - fprintf(stderr, "WE_HAVE_A_SCALE\n"); -#endif - a = GetInt16(ptr, 0, 1) << 2; - d = a; - ptr += 2; - } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) { -#ifdef DEBUG2 - fprintf(stderr, "WE_HAVE_AN_X_AND_Y_SCALE\n"); -#endif - a = GetInt16(ptr, 0, 1) << 2; - d = GetInt16(ptr, 2, 1) << 2; - ptr += 4; - } else if (flags & WE_HAVE_A_TWO_BY_TWO) { -#ifdef DEBUG2 - fprintf(stderr, "WE_HAVE_A_TWO_BY_TWO\n"); -#endif - a = GetInt16(ptr, 0, 1) << 2; - b = GetInt16(ptr, 2, 1) << 2; - c = GetInt16(ptr, 4, 1) << 2; - d = GetInt16(ptr, 6, 1) << 2; - ptr += 8; - } - - abs1 = (a < 0) ? -a : a; - abs2 = (b < 0) ? -b : b; - m = (abs1 > abs2) ? abs1 : abs2; - abs3 = abs1 - abs2; - if (abs3 < 0) abs3 = -abs3; - if (abs3 <= 33) m *= 2; - - abs1 = (c < 0) ? -c : c; - abs2 = (d < 0) ? -d : d; - n = (abs1 > abs2) ? abs1 : abs2; - abs3 = abs1 - abs2; - if (abs3 < 0) abs3 = -abs3; - if (abs3 <= 33) n *= 2; - - if (!ARGS_ARE_XY_VALUES) { /* match the points */ - assert(!"ARGS_ARE_XY_VALUES is not implemented!!!\n"); - } - -#ifdef DEBUG2 - fprintf(stderr, "a: %f, b: %f, c: %f, d: %f, e: %f, f: %f, m: %f, n: %f\n", - ((double) a) / 65536, - ((double) b) / 65536, - ((double) c) / 65536, - ((double) d) / 65536, - ((double) e) / 65536, - ((double) f) / 65536, - ((double) m) / 65536, - ((double) n) / 65536); -#endif - - for (i=0; i<np; i++) { - F16Dot16 t; - ControlPoint *cp = malloc(sizeof(ControlPoint)); - cp->flags = nextComponent[i].flags; - t = fixedMulDiv(a, nextComponent[i].x << 16, m) + fixedMulDiv(c, nextComponent[i].y << 16, m) + (e << 16); - cp->x = (sal_Int16)(fixedMul(t, m) >> 16); - t = fixedMulDiv(b, nextComponent[i].x << 16, n) + fixedMulDiv(d, nextComponent[i].y << 16, n) + (f << 16); - cp->y = (sal_Int16)(fixedMul(t, n) >> 16); - -#ifdef DEBUG2 - fprintf(stderr, "( %d %d ) -> ( %d %d )\n", nextComponent[i].x, nextComponent[i].y, cp->x, cp->y); -#endif - - listAppend(myPoints, cp); - } - - free(nextComponent); - - } while (flags & MORE_COMPONENTS); - - - - np = listCount(myPoints); - - pa = calloc(np, sizeof(ControlPoint)); - assert(pa != 0); - listToFirst(myPoints); - for (i=0; i<np; i++) { - memcpy(pa+i, listCurrent(myPoints), sizeof(ControlPoint)); - listNext(myPoints); - } - listDispose(myPoints); - - *pointArray = pa; - return np; -} - -/* NOTE: GetTTGlyphOutline() returns -1 if the glyphID is incorrect, - * but Get{Simple|Compound}GlyphOutline returns 0 in such a case. - * - * NOTE: glyphlist is the stack of glyphs traversed while constructing - * a composite glyph. This is a safequard against endless recursion - * in corrupted fonts. - */ -static int GetTTGlyphOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, list glyphlist) -{ - sal_uInt8 *ptr, *table = getTable(ttf, O_glyf); - sal_Int16 numberOfContours; - int length; - int res; - *pointArray = 0; - - if (metrics) { - memset(metrics, 0, sizeof(TTGlyphMetrics)); /*- metrics is initialized to all zeroes */ - } - - if (glyphID >= ttf->nglyphs) return -1; /**/ - - ptr = table + ttf->goffsets[glyphID]; - length = ttf->goffsets[glyphID+1] - ttf->goffsets[glyphID]; - - if (length == 0) { /*- empty glyphs still have hmtx and vmtx metrics values */ - if (metrics) GetMetrics(ttf, glyphID, metrics); - return 0; - } - - numberOfContours = GetInt16(ptr, 0, 1); - - if (numberOfContours >= 0) { - res=GetSimpleTTOutline(ttf, glyphID, pointArray, metrics); - } else { - int glyphlistFlag = 0; - if (!glyphlist) { - glyphlistFlag = 1; - glyphlist = listNewEmpty(); - listAppend(glyphlist, (void *) (sal_IntPtr) glyphID); - } - res = GetCompoundTTOutline(ttf, glyphID, pointArray, metrics, glyphlist); - if (glyphlistFlag) { - glyphlistFlag = 0; - listDispose(glyphlist); - glyphlist = 0; - } - } - -#ifdef DEBUG3 - { - int i; - FILE *out = fopen("points.dat", "a"); - assert(out != 0); - fprintf(out, "Glyph: %d\nPoints: %d\n", glyphID, res); - for (i=0; i<res; i++) { - fprintf(out, "%c ", ((*pointArray)[i].flags & 0x8000) ? 'X' : '.'); - fprintf(out, "%c ", ((*pointArray)[i].flags & 1) ? '+' : '-'); - fprintf(out, "%d %d\n", (*pointArray)[i].x, (*pointArray)[i].y); - } - fclose(out); - } -#endif - - return res; -} - -#ifndef NO_TYPE3 - -static PSPathElement *newPSPathElement(int t) -{ - PSPathElement *p = malloc(sizeof(PSPathElement)); - assert(p != 0); - - p->type = t; - return p; -} - -/*- returns the number of items in the path -*/ - -static int BSplineToPSPath(ControlPoint *srcA, int srcCount, PSPathElement **path) -{ - list pList = listNewEmpty(); - int i = 0, pCount = 0; - PSPathElement *p; - - int x0 = 0, y0 = 0, x1 = 0, y1 = 0, x2, y2, curx, cury; - int lastOff = 0; /*- last point was off-contour */ - int scflag = 1; /*- start contour flag */ - int ecflag = 0; /*- end contour flag */ - int cp = 0; /*- current point */ - int StartContour = 0, EndContour = 1; - - listSetElementDtor(pList, free); - *path = 0; - - /* if (srcCount > 0) for(;;) */ - while (srcCount > 0) { /*- srcCount does not get changed inside the loop. */ - if (scflag) { - int l = cp; - StartContour = cp; - while (!(srcA[l].flags & 0x8000)) l++; - EndContour = l; - if (StartContour == EndContour) { - if (cp + 1 < srcCount) { - cp++; - continue; - } else { - break; - } - } - p = newPSPathElement(PS_MOVETO); - if (!(srcA[cp].flags & 1)) { - if (!(srcA[EndContour].flags & 1)) { - p->x1 = x0 = (srcA[cp].x + srcA[EndContour].x + 1) / 2; - p->y1 = y0 = (srcA[cp].y + srcA[EndContour].y + 1) / 2; - } else { - p->x1 = x0 = srcA[EndContour].x; - p->y1 = y0 = srcA[EndContour].y; - } - } else { - p->x1 = x0 = srcA[cp].x; - p->y1 = y0 = srcA[cp].y; - cp++; - } - listAppend(pList, p); - lastOff = 0; - scflag = 0; - } - - curx = srcA[cp].x; - cury = srcA[cp].y; - - if (srcA[cp].flags & 1) { - if (lastOff) { - p = newPSPathElement(PS_CURVETO); - p->x1 = x0 + (2 * (x1 - x0) + 1) / 3; - p->y1 = y0 + (2 * (y1 - y0) + 1) / 3; - p->x2 = x1 + (curx - x1 + 1) / 3; - p->y2 = y1 + (cury - y1 + 1) / 3; - p->x3 = curx; - p->y3 = cury; - listAppend(pList, p); - } else { - if (!(x0 == curx && y0 == cury)) { /* eliminate empty lines */ - p = newPSPathElement(PS_LINETO); - p->x1 = curx; - p->y1 = cury; - listAppend(pList, p); - } - } - - x0 = curx; y0 = cury; lastOff = 0; - } else { - if (lastOff) { - x2 = (x1 + curx + 1) / 2; - y2 = (y1 + cury + 1) / 2; - p = newPSPathElement(PS_CURVETO); - p->x1 = x0 + (2 * (x1 - x0) + 1) / 3; - p->y1 = y0 + (2 * (y1 - y0) + 1) / 3; - p->x2 = x1 + (x2 - x1 + 1) / 3; - p->y2 = y1 + (y2 - y1 + 1) / 3; - p->x3 = x2; - p->y3 = y2; - listAppend(pList, p); - x0 = x2; y0 = y2; - x1 = curx; y1 = cury; - } else { - x1 = curx; y1 = cury; - } - lastOff = true; - } - - if (ecflag) { - listAppend(pList, newPSPathElement(PS_CLOSEPATH)); - scflag = 1; - ecflag = 0; - cp = EndContour + 1; - if (cp >= srcCount) break; - continue; - } - - - if (cp == EndContour) { - cp = StartContour; - ecflag = true; - } else { - cp++; - } - } - - if ((pCount = listCount(pList)) > 0) { - p = calloc(pCount, sizeof(PSPathElement)); - assert(p != 0); - listToFirst(pList); - for (i=0; i<pCount; i++) { - memcpy(p + i, listCurrent(pList), sizeof(PSPathElement)); - listNext(pList); - } - *path = p; - } - listDispose(pList); - - return pCount; -} - -#endif - -/*- Extracts a string from the name table and allocates memory for it -*/ - -static char *nameExtract(sal_uInt8 *name, int nTableSize, int n, int dbFlag, sal_uInt16** ucs2result ) -{ - int i; - char *res; - sal_uInt8 *ptr = name + GetUInt16(name, 4, 1) + GetUInt16(name + 6, 12 * n + 10, 1); - int len = GetUInt16(name+6, 12 * n + 8, 1); - - // sanity check - if( ! len || ptr >= (name+nTableSize-len) ) - { - if( ucs2result ) - *ucs2result = NULL; - return NULL; - } - - if( ucs2result ) - *ucs2result = NULL; - if (dbFlag) { - res = malloc(1 + len/2); - assert(res != 0); - for (i = 0; i < len/2; i++) res[i] = *(ptr + i * 2 + 1); - res[len/2] = 0; - if( ucs2result ) - { - *ucs2result = malloc( len+2 ); - for (i = 0; i < len/2; i++ ) (*ucs2result)[i] = GetUInt16( ptr, 2*i, 1 ); - (*ucs2result)[len/2] = 0; - } - } else { - res = malloc(1 + len); - assert(res != 0); - memcpy(res, ptr, len); - res[len] = 0; - } - - return res; -} - -static int findname(sal_uInt8 *name, sal_uInt16 n, sal_uInt16 platformID, sal_uInt16 encodingID, sal_uInt16 languageID, sal_uInt16 nameID) -{ - int l = 0, r = n-1, i; - sal_uInt32 t1, t2; - sal_uInt32 m1, m2; - - if (n == 0) return -1; - - m1 = (platformID << 16) | encodingID; - m2 = (languageID << 16) | nameID; - - do { - i = (l + r) >> 1; - t1 = GetUInt32(name + 6, i * 12 + 0, 1); - t2 = GetUInt32(name + 6, i * 12 + 4, 1); - - if (! ((m1 < t1) || ((m1 == t1) && (m2 < t2)))) l = i + 1; - if (! ((m1 > t1) || ((m1 == t1) && (m2 > t2)))) r = i - 1; - } while (l <= r); - - if (l - r == 2) { - return l - 1; - } - - return -1; -} - -/* XXX marlett.ttf uses (3, 0, 1033) instead of (3, 1, 1033) and does not have any Apple tables. - * Fix: if (3, 1, 1033) is not found - need to check for (3, 0, 1033) - * - * /d/fonts/ttzh_tw/Big5/Hanyi/ma6b5p uses (1, 0, 19) for English strings, instead of (1, 0, 0) - * and does not have (3, 1, 1033) - * Fix: if (1, 0, 0) and (3, 1, 1033) are not found need to look for (1, 0, *) - that will - * require a change in algorithm - * - * /d/fonts/fdltest/Korean/h2drrm has unsorted names and a an unknown (to me) Mac LanguageID, - * but (1, 0, 1042) strings usable - * Fix: change algorithm, and use (1, 0, *) if both standard Mac and MS strings are not found - */ - -static void GetNames(TrueTypeFont *t) -{ - sal_uInt8 *table = getTable(t, O_name); - int nTableSize = getTableSize(t, O_name); - - sal_uInt16 n = GetUInt16(table, 2, 1); - int i, r; - sal_Bool bPSNameOK = sal_True; - - /* #129743# simple sanity check for name table entry count */ - if( nTableSize <= n * 12 + 6 ) - n = 0; - - /* PostScript name: preferred Microsoft */ - t->psname = NULL; - if ((r = findname(table, n, 3, 1, 0x0409, 6)) != -1) - t->psname = nameExtract(table, nTableSize, r, 1, NULL); - if ( ! t->psname && (r = findname(table, n, 1, 0, 0, 6)) != -1) - t->psname = nameExtract(table, nTableSize, r, 0, NULL); - if ( ! t->psname && (r = findname(table, n, 3, 0, 0x0409, 6)) != -1) - { - // some symbol fonts like Marlett have a 3,0 name! - t->psname = nameExtract(table, nTableSize, r, 1, NULL); - } - if ( ! t->psname ) - { - if ( t->fname ) - { - char* pReverse = t->fname + strlen(t->fname); - /* take only last token of filename */ - while(pReverse != t->fname && *pReverse != '/') pReverse--; - if(*pReverse == '/') pReverse++; - t->psname = strdup(pReverse); - assert(t->psname != 0); - for (i=strlen(t->psname) - 1; i > 0; i--) - { - /*- Remove the suffix -*/ - if (t->psname[i] == '.' ) { - t->psname[i] = 0; - break; - } - } - } - else - t->psname = strdup( "Unknown" ); - } - - /* Font family and subfamily names: preferred Apple */ - t->family = NULL; - if ((r = findname(table, n, 0, 0, 0, 1)) != -1) - t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily); - if ( ! t->family && (r = findname(table, n, 3, 1, 0x0409, 1)) != -1) - t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily); - if ( ! t->family && (r = findname(table, n, 1, 0, 0, 1)) != -1) - t->family = nameExtract(table, nTableSize, r, 0, NULL); - if ( ! t->family && (r = findname(table, n, 3, 1, 0x0411, 1)) != -1) - t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily); - if ( ! t->family && (r = findname(table, n, 3, 0, 0x0409, 1)) != -1) - t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily); - if ( ! t->family ) - { - t->family = strdup(t->psname); - assert(t->family != 0); - } - - t->subfamily = NULL; - t->usubfamily = NULL; - if ((r = findname(table, n, 1, 0, 0, 2)) != -1) - t->subfamily = nameExtract(table, nTableSize, r, 0, &t->usubfamily); - if ( ! t->subfamily && (r = findname(table, n, 3, 1, 0x0409, 2)) != -1) - t->subfamily = nameExtract(table, nTableSize, r, 1, &t->usubfamily); - if ( ! t->subfamily ) - { - t->subfamily = strdup(""); - } - - /* #i60349# sanity check psname - * psname parctically has to be 7bit ascii and should not contains spaces - * there is a class of broken fonts which do not fullfill that at all, so let's try - * if the family name is 7bit ascii and take it instead if so - */ - /* check psname */ - for( i = 0; t->psname[i] != 0 && bPSNameOK; i++ ) - if( t->psname[ i ] < 33 || (t->psname[ i ] & 0x80) ) - bPSNameOK = sal_False; - if( bPSNameOK == sal_False ) - { - sal_Bool bReplace = sal_True; - /* check if family is a suitable replacement */ - if( t->ufamily && t->family ) - { - for( i = 0; t->ufamily[ i ] != 0 && bReplace; i++ ) - if( t->ufamily[ i ] < 33 || t->ufamily[ i ] > 127 ) - bReplace = sal_False; - if( bReplace ) - { - free( t->psname ); - t->psname = strdup( t->family ); - } - } - } -} - -enum cmapType { - CMAP_NOT_USABLE = -1, - CMAP_MS_Symbol = 10, - CMAP_MS_Unicode = 11, - CMAP_MS_ShiftJIS = 12, - CMAP_MS_Big5 = 13, - CMAP_MS_PRC = 14, - CMAP_MS_Wansung = 15, - CMAP_MS_Johab = 16 -}; - -#define MISSING_GLYPH_INDEX 0 - -/* - * getGlyph[0246]() functions and freinds are implemented by: - * @author Manpreet Singh - * getGlyph12() function and friends by: - * @author HDU - */ -static sal_uInt32 getGlyph0(const sal_uInt8* cmap, sal_uInt32 c) { - if (c <= 255) { - return *(cmap + 6 + c); - } else { - return MISSING_GLYPH_INDEX; - } -} - -typedef struct _subHeader2 { - sal_uInt16 firstCode; - sal_uInt16 entryCount; - sal_uInt16 idDelta; - sal_uInt16 idRangeOffset; -} subHeader2; - -static sal_uInt32 getGlyph2(const sal_uInt8 *cmap, sal_uInt32 c) { - sal_uInt16 *CMAP2 = (sal_uInt16 *) cmap; - sal_uInt8 theHighByte; - - sal_uInt8 theLowByte; - subHeader2* subHeader2s; - sal_uInt16* subHeader2Keys; - sal_uInt16 firstCode; - int k; - sal_uInt32 ToReturn; - - theHighByte = (sal_uInt8)((c >> 8) & 0x00ff); - theLowByte = (sal_uInt8)(c & 0x00ff); - subHeader2Keys = CMAP2 + 3; - subHeader2s = (subHeader2 *)(subHeader2Keys + 256); - k = Int16FromMOTA(subHeader2Keys[theHighByte]) / 8; - - if(k == 0) { - firstCode = Int16FromMOTA(subHeader2s[k].firstCode); - if(theLowByte >= firstCode && theLowByte < (firstCode + Int16FromMOTA(subHeader2s[k].entryCount))) { - return *((&(subHeader2s[0].idRangeOffset)) - + (Int16FromMOTA(subHeader2s[0].idRangeOffset)/2) /* + offset */ - + theLowByte /* + to_look */ - - Int16FromMOTA(subHeader2s[0].firstCode) - ); - } else { - return MISSING_GLYPH_INDEX; - } - } else if (k > 0) { - firstCode = Int16FromMOTA(subHeader2s[k].firstCode); - if(theLowByte >= firstCode && theLowByte < (firstCode + Int16FromMOTA(subHeader2s[k].entryCount))) { - ToReturn = *((&(subHeader2s[k].idRangeOffset)) - + (Int16FromMOTA(subHeader2s[k].idRangeOffset)/2) - + theLowByte - firstCode); - if(ToReturn == 0) { - return MISSING_GLYPH_INDEX; - } else { - ToReturn += Int16FromMOTA(subHeader2s[k].idDelta); - return (ToReturn & 0xFFFF); - } - } else { - return MISSING_GLYPH_INDEX; - } - } else { - return MISSING_GLYPH_INDEX; - } -} - -static sal_uInt32 getGlyph6(const sal_uInt8 *cmap, sal_uInt32 c) { - sal_uInt16 firstCode, lastCode, count; - sal_uInt16 *CMAP6 = (sal_uInt16 *) cmap; - - firstCode = Int16FromMOTA(*(CMAP6 + 3)); - count = Int16FromMOTA(*(CMAP6 + 4)); - lastCode = firstCode + count - 1; - if (c < firstCode || c > lastCode) { - return MISSING_GLYPH_INDEX; - } else { - return *((CMAP6 + 5)/*glyphIdArray*/ + (c - firstCode)); - } -} - -static sal_uInt16 GEbinsearch(sal_uInt16 *ar, sal_uInt16 length, sal_uInt16 toSearch) { - signed int low, mid, high, lastfound = 0xffff; - sal_uInt16 res; - if(length == (sal_uInt16)0 || length == (sal_uInt16)0xFFFF) { - return (sal_uInt16)0xFFFF; - } - low = 0; - high = length - 1; - while(high >= low) { - mid = (high + low)/2; - res = Int16FromMOTA(*(ar+mid)); - if(res >= toSearch) { - lastfound = mid; - high = --mid; - } else { - low = ++mid; - } - } - return (sal_uInt16)lastfound; -} - - -static sal_uInt32 getGlyph4(const sal_uInt8 *cmap, sal_uInt32 c) { - sal_uInt16 i; - int ToReturn; - sal_uInt16 segCount; - sal_uInt16 * startCode; - sal_uInt16 * endCode; - sal_uInt16 * idDelta; - /* sal_uInt16 * glyphIdArray; */ - sal_uInt16 * idRangeOffset; - sal_uInt16 * glyphIndexArray; - sal_uInt16 *CMAP4 = (sal_uInt16 *) cmap; - /* sal_uInt16 GEbinsearch(sal_uInt16 *ar, sal_uInt16 length, sal_uInt16 toSearch); */ - - segCount = Int16FromMOTA(*(CMAP4 + 3))/2; - endCode = CMAP4 + 7; - i = GEbinsearch(endCode, segCount, (sal_uInt16)c); - - if (i == (sal_uInt16) 0xFFFF) { - return MISSING_GLYPH_INDEX; - } - startCode = endCode + segCount + 1; - - if(Int16FromMOTA(startCode[i]) > c) { - return MISSING_GLYPH_INDEX; - } - idDelta = startCode + segCount; - idRangeOffset = idDelta + segCount; - glyphIndexArray = idRangeOffset + segCount; - - if(Int16FromMOTA(idRangeOffset[i]) != 0) { - c = Int16FromMOTA(*(&(idRangeOffset[i]) + (Int16FromMOTA(idRangeOffset[i])/2 + (c - Int16FromMOTA(startCode[i]))))); - } - - ToReturn = (Int16FromMOTA(idDelta[i]) + c) & 0xFFFF; - return ToReturn; -} - -static sal_uInt32 getGlyph12(const sal_uInt8 *pCmap, sal_uInt32 cChar) { - const sal_uInt32* pCMAP12 = (const sal_uInt32*)pCmap; - int nLength = Int32FromMOTA( pCMAP12[1] ); - int nGroups = Int32FromMOTA( pCMAP12[3] ); - int nLower = 0; - int nUpper = nGroups; - - if( nUpper > (nLength-16)/12 ) - nUpper = (nLength-16)/12; - - /* binary search in "segmented coverage" subtable */ - while( nLower < nUpper ) { - int nIndex = (nLower + nUpper) / 2; - const sal_uInt32* pEntry = &pCMAP12[ 4 + 3*nIndex ]; - sal_uInt32 cStart = Int32FromMOTA( pEntry[0] ); - sal_uInt32 cLast = Int32FromMOTA( pEntry[1] ); - if( cChar < cStart ) - nUpper = nIndex; - else if( cChar > cLast ) - nLower = nIndex + 1; - else { /* found matching entry! */ - sal_uInt32 nGlyph = Int32FromMOTA( pEntry[2] ); - nGlyph += cChar - cStart; - return nGlyph; - } - } - - return MISSING_GLYPH_INDEX; -} - - -static void FindCmap(TrueTypeFont *ttf) -{ - sal_uInt8 *table = getTable(ttf, O_cmap); - sal_uInt32 table_size = getTableSize(ttf, O_cmap); - sal_uInt16 ncmaps = GetUInt16(table, 2, 1); - unsigned int i; - sal_uInt32 ThreeZero = 0; /* MS Symbol */ - sal_uInt32 ThreeOne = 0; /* MS UCS-2 */ - sal_uInt32 ThreeTwo = 0; /* MS ShiftJIS */ - sal_uInt32 ThreeThree = 0; /* MS Big5 */ - sal_uInt32 ThreeFour = 0; /* MS PRC */ - sal_uInt32 ThreeFive = 0; /* MS Wansung */ - sal_uInt32 ThreeSix = 0; /* MS Johab */ - - for (i = 0; i < ncmaps; i++) { - sal_uInt32 offset; - sal_uInt16 pID, eID; - - /* sanity check, cmap entry must lie within table */ - if( i*8+4 > table_size ) - break; - - pID = GetUInt16(table, 4 + i * 8, 1); - eID = GetUInt16(table, 6 + i * 8, 1); - offset = GetUInt32(table, 8 + i * 8, 1); - - /* sanity check, cmap must lie within file */ - if( (table - ttf->ptr) + offset > (sal_uInt32)ttf->fsize ) - continue; - - /* Unicode tables in Apple fonts */ - if (pID == 0) { - ThreeOne = offset; break; - } - - if (pID == 3) { - switch (eID) { - case 0: ThreeZero = offset; break; - case 10: // UCS-4 - case 1: ThreeOne = offset; break; - case 2: ThreeTwo = offset; break; - case 3: ThreeThree = offset; break; - case 4: ThreeFour = offset; break; - case 5: ThreeFive = offset; break; - case 6: ThreeSix = offset; break; - } - } - } - - if (ThreeOne) { - ttf->cmapType = CMAP_MS_Unicode; - ttf->cmap = table + ThreeOne; - } else if (ThreeTwo) { - ttf->cmapType = CMAP_MS_ShiftJIS; - ttf->cmap = table + ThreeTwo; - } else if (ThreeThree) { - ttf->cmapType = CMAP_MS_Big5; - ttf->cmap = table + ThreeThree; - } else if (ThreeFour) { - ttf->cmapType = CMAP_MS_PRC; - ttf->cmap = table + ThreeFour; - } else if (ThreeFive) { - ttf->cmapType = CMAP_MS_Wansung; - ttf->cmap = table + ThreeFive; - } else if (ThreeSix) { - ttf->cmapType = CMAP_MS_Johab; - ttf->cmap = table + ThreeSix; - } else if (ThreeZero) { - ttf->cmapType = CMAP_MS_Symbol; - ttf->cmap = table + ThreeZero; - } else { - ttf->cmapType = CMAP_NOT_USABLE; - ttf->cmap = 0; - } - - if (ttf->cmapType != CMAP_NOT_USABLE) { - switch (GetUInt16(ttf->cmap, 0, 1)) { - case 0: ttf->mapper = getGlyph0; break; - case 2: ttf->mapper = getGlyph2; break; - case 4: ttf->mapper = getGlyph4; break; - case 6: ttf->mapper = getGlyph6; break; - case 12: ttf->mapper= getGlyph12; break; - default: -#if OSL_DEBUG_LEVEL > 1 - /*- if the cmap table is really broken */ - printf("%s: %d is not a recognized cmap format.\n", ttf->fname, GetUInt16(ttf->cmap, 0, 1)); -#endif - ttf->cmapType = CMAP_NOT_USABLE; - ttf->cmap = 0; - ttf->mapper = 0; - } - } -} - -static void GetKern(TrueTypeFont *ttf) -{ - sal_uInt8 *table = getTable(ttf, O_kern); - sal_uInt8 *ptr; - sal_uInt32 i; - /* - sal_uInt16 v1; - sal_uInt32 v2; - */ - - if (!table) goto badtable; - - if (GetUInt16(table, 0, 1) == 0) { /* Traditional Microsoft style table with USHORT version and nTables fields */ - ttf->nkern = GetUInt16(table, 2, 1); - ttf->kerntables = calloc(ttf->nkern, sizeof(sal_uInt8 *)); - assert(ttf->kerntables != 0); - memset(ttf->kerntables, 0, ttf->nkern * sizeof(sal_uInt8 *)); - ttf->kerntype = KT_MICROSOFT; - ptr = table + 4; - for (i=0; i < ttf->nkern; i++) { - ttf->kerntables[i] = ptr; - ptr += GetUInt16(ptr, 2, 1); - /* sanity check */ - if( ptr > ttf->ptr+ttf->fsize ) - { - free( ttf->kerntables ); - goto badtable; - } - } - return; - } - - if (GetUInt32(table, 0, 1) == 0x00010000) { /* MacOS style kern tables: fixed32 version and sal_uInt32 nTables fields */ - ttf->nkern = GetUInt32(table, 4, 1); - ttf->kerntables = calloc(ttf->nkern, sizeof(sal_uInt8 *)); - assert(ttf->kerntables != 0); - memset(ttf->kerntables, 0, ttf->nkern * sizeof(sal_uInt8 *)); - ttf->kerntype = KT_APPLE_NEW; - ptr = table + 8; - for (i = 0; i < ttf->nkern; i++) { - ttf->kerntables[i] = ptr; - ptr += GetUInt32(ptr, 0, 1); - /* sanity check; there are some fonts that are broken in this regard */ - if( ptr > ttf->ptr+ttf->fsize ) - { - free( ttf->kerntables ); - goto badtable; - } - } - return; - } - - badtable: - ttf->kerntype = KT_NONE; - ttf->kerntables = 0; - - return; -} - -#ifdef TEST5 -/* KernGlyphsPrim?() functions expect the caller to ensure the validity of their arguments and - * that x and y elements of the kern array are initialized to zeroes - */ -static void KernGlyphsPrim1(TrueTypeFont *ttf, sal_uInt16 *glyphs, int nglyphs, int wmode, KernData *kern) -{ - (void)ttf; /* avoid warning */ - (void)glyphs; /* avoid warning */ - (void)nglyphs; /* avoid warning */ - (void)wmode; /* avoid warning */ - (void)nglyphs; /* avoid warning */ - (void)kern; /* avoid warning */ - fprintf(stderr, "MacOS kerning tables have not been implemented yet!\n"); -} - -static void KernGlyphsPrim2(TrueTypeFont *ttf, sal_uInt16 *glyphs, int nglyphs, int wmode, KernData *kern) -{ - sal_uInt32 i, j; - sal_uInt32 gpair; - - if( ! nglyphs ) - return; - - for (i = 0; i < (sal_uInt32)nglyphs - 1; i++) { - gpair = (glyphs[i] << 16) | glyphs[i+1]; -#ifdef DEBUG2 - /* All fonts with MS kern table that I've seen so far contain just one kern subtable. - * MS kern documentation is very poor and I doubt that font developers will be using - * several subtables. I expect them to be using OpenType tables instead. - * According to MS documention, format 2 subtables are not supported by Windows and OS/2. - */ - if (ttf->nkern > 1) { - fprintf(stderr, "KernGlyphsPrim2: %d kern tables found.\n", ttf->nkern); - } -#endif - for (j = 0; j < ttf->nkern; j++) { - sal_uInt16 coverage = GetUInt16(ttf->kerntables[j], 4, 1); - sal_uInt8 *ptr; - int npairs; - sal_uInt32 t; - int l, r, k; - - if (! ((coverage & 1) ^ wmode)) continue; - if ((coverage & 0xFFFE) != 0) { -#ifdef DEBUG2 - fprintf(stderr, "KernGlyphsPrim2: coverage flags are not supported: %04X.\n", coverage); -#endif - continue; - } - ptr = ttf->kerntables[j]; - npairs = GetUInt16(ptr, 6, 1); - ptr += 14; - l = 0; - r = npairs; - do { - k = (l + r) >> 1; - t = GetUInt32(ptr, k * 6, 1); - if (gpair >= t) l = k + 1; - if (gpair <= t) r = k - 1; - } while (l <= r); - if (l - r == 2) { - if (!wmode) { - kern[i].x = XUnits(ttf->unitsPerEm, GetInt16(ptr, 4 + (l-1) * 6, 1)); - } else { - kern[i].y = XUnits(ttf->unitsPerEm, GetInt16(ptr, 4 + (l-1) * 6, 1)); - } - /* !wmode ? kern[i].x : kern[i].y = GetInt16(ptr, 4 + (l-1) * 6, 1); */ - } - } - } -} -#endif - -/*- Public functions */ /*FOLD00*/ - -int CountTTCFonts(const char* fname) -{ - int nFonts = 0; - sal_uInt8 buffer[12]; - FILE* fd = fopen(fname, "rb"); - if( fd ) { - if (fread(buffer, 1, 12, fd) == 12) { - if(GetUInt32(buffer, 0, 1) == T_ttcf ) - nFonts = GetUInt32(buffer, 8, 1); - } - fclose(fd); - } - return nFonts; -} - -static void allocTrueTypeFont( TrueTypeFont** ttf ) -{ - *ttf = calloc(1,sizeof(TrueTypeFont)); - if( *ttf != NULL ) - { - (*ttf)->tag = 0; - (*ttf)->fname = 0; - (*ttf)->fsize = -1; - (*ttf)->ptr = 0; - (*ttf)->nglyphs = 0xFFFFFFFF; - (*ttf)->pGSubstitution = 0; - } -} - -/* forward declariotn for the two entry points to use*/ -static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t ); - -#if !defined(WIN32) && !defined(OS2) -int OpenTTFontFile( const char* fname, sal_uInt32 facenum, TrueTypeFont** ttf ) -{ - int ret, fd = -1; - struct stat st; - - if (!fname || !*fname) return SF_BADFILE; - - allocTrueTypeFont( ttf ); - if( ! *ttf ) - return SF_MEMORY; - - (*ttf)->fname = strdup(fname); - if( ! (*ttf)->fname ) - { - ret = SF_MEMORY; - goto cleanup; - } - - fd = open(fname, O_RDONLY); - - if (fd == -1) { - ret = SF_BADFILE; - goto cleanup; - } - - if (fstat(fd, &st) == -1) { - ret = SF_FILEIO; - goto cleanup; - } - - (*ttf)->fsize = st.st_size; - - /* On Mac OS, most likely will happen if a Mac user renames a font file - * to be .ttf when its really a Mac resource-based font. - * Size will be 0, but fonts smaller than 4 bytes would be broken anyway. - */ - if ((*ttf)->fsize == 0) { - ret = SF_BADFILE; - goto cleanup; - } - - - if (((*ttf)->ptr = (sal_uInt8 *) mmap(0, (*ttf)->fsize, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { - ret = SF_MEMORY; - goto cleanup; - } - close(fd); - - return doOpenTTFont( facenum, *ttf ); - -cleanup: - if (fd != -1) close(fd); - /*- t and t->fname have been allocated! */ - free((*ttf)->fname); - free(*ttf); - *ttf = NULL; - return ret; -} -#endif - -int OpenTTFontBuffer(void* pBuffer, sal_uInt32 nLen, sal_uInt32 facenum, TrueTypeFont** ttf) -{ - allocTrueTypeFont( ttf ); - if( *ttf == NULL ) - return SF_MEMORY; - - (*ttf)->fname = NULL; - (*ttf)->fsize = nLen; - (*ttf)->ptr = pBuffer; - - return doOpenTTFont( facenum, *ttf ); -} - -static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t ) -{ - int i; - sal_uInt32 version; - sal_uInt8 *table, *offset; - sal_uInt32 length, tag; - sal_uInt32 tdoffset = 0; /* offset to TableDirectory in a TTC file. For TTF files is 0 */ - int indexfmt, k; - - version = GetInt32(t->ptr, 0, 1); - - if ((version == 0x00010000) || (version == T_true)) { - tdoffset = 0; - } else if (version == T_ttcf) { /*- TrueType collection */ - if (GetUInt32(t->ptr, 4, 1) != 0x00010000) { - CloseTTFont(t); - return SF_TTFORMAT; - } - if (facenum >= GetUInt32(t->ptr, 8, 1)) { - CloseTTFont(t); - return SF_FONTNO; - } - tdoffset = GetUInt32(t->ptr, 12 + 4 * facenum, 1); - } else { - CloseTTFont(t); - return SF_TTFORMAT; - } - -#ifdef DEBUG2 - fprintf(stderr, "tdoffset: %d\n", tdoffset); -#endif - - /* magic number */ - t->tag = TTFontClassTag; - - t->ntables = GetUInt16(t->ptr + tdoffset, 4, 1); - if( t->ntables >= 128 ) - return SF_TTFORMAT; - - t->tables = calloc(NUM_TAGS, sizeof(void *)); - assert(t->tables != 0); - t->tlens = calloc(NUM_TAGS, sizeof(sal_uInt32)); - assert(t->tlens != 0); - - memset(t->tables, 0, NUM_TAGS * sizeof(void *)); - memset(t->tlens, 0, NUM_TAGS * sizeof(sal_uInt32)); - - /* parse the tables */ - for (i=0; i<(int)t->ntables; i++) { - int nIndex; - tag = GetUInt32(t->ptr + tdoffset + 12, 16 * i, 1); - switch( tag ) { - case T_maxp: nIndex = O_maxp; break; - case T_glyf: nIndex = O_glyf; break; - case T_head: nIndex = O_head; break; - case T_loca: nIndex = O_loca; break; - case T_name: nIndex = O_name; break; - case T_hhea: nIndex = O_hhea; break; - case T_hmtx: nIndex = O_hmtx; break; - case T_cmap: nIndex = O_cmap; break; - case T_vhea: nIndex = O_vhea; break; - case T_vmtx: nIndex = O_vmtx; break; - case T_OS2 : nIndex = O_OS2; break; - case T_post: nIndex = O_post; break; - case T_kern: nIndex = O_kern; break; - case T_cvt : nIndex = O_cvt; break; - case T_prep: nIndex = O_prep; break; - case T_fpgm: nIndex = O_fpgm; break; - case T_gsub: nIndex = O_gsub; break; - default: nIndex = -1; break; - } - if( nIndex >= 0 ) { - offset = t->ptr + GetUInt32(t->ptr + tdoffset + 12, 16 * i + 8, 1); - length = GetUInt32(t->ptr + tdoffset + 12, 16 * i + 12, 1); - t->tables[nIndex] = offset; - t->tlens[nIndex] = length; - } - } - - /* Fixup offsets when only a TTC extract was provided */ - if( facenum == (sal_uInt32)~0 ) { - sal_uInt8 *pHead = t->tables[O_head], *p = NULL; - if( !pHead ) - return SF_TTFORMAT; - /* limit Head candidate to TTC extract's limits */ - if( pHead > t->ptr + (t->fsize - 54) ) - pHead = t->ptr + (t->fsize - 54); - /* TODO: find better method than searching head table's magic */ - for( p = pHead + 12; p > t->ptr; --p ) { - if( p[0]==0x5F && p[1]==0x0F && p[2]==0x3C && p[3]==0xF5 ) { - int nDelta = (pHead + 12) - p, j; - if( nDelta ) - for( j=0; j<NUM_TAGS; ++j ) - if( t->tables[j] ) - *(char**)&t->tables[j] -= nDelta; - break; - } - } - if( p <= t->ptr ) - return SF_TTFORMAT; - } - - /* Check the table offsets after TTC correction */ - for (i=0; i<NUM_TAGS; i++) { - /* sanity check: table must lay completely within the file - * at this point one could check the checksum of all contained - * tables, but this would be quite time intensive. - * Try to fix tables, so we can cope with minor problems. - */ - - if( (sal_uInt8*)t->tables[i] < t->ptr ) - { - t->tlens[i] = 0; - t->tables[i] = NULL; -#if OSL_DEBUG_LEVEL > 1 - fprintf( stderr, "font file %s has bad table offset (tagnum=%d)\n", t->fname, i ); -#endif - } - else if( (sal_uInt8*)t->tables[i] + t->tlens[i] > t->ptr + t->fsize ) - { - int nMaxLen = (t->ptr + t->fsize) - (sal_uInt8*)t->tables[i]; - if( nMaxLen < 0 ) - nMaxLen = 0; - t->tlens[i] = nMaxLen; -#if OSL_DEBUG_LEVEL > 1 - fprintf( stderr, "font file %s has too big table (tagnum=%d)\n", t->fname, i ); -#endif - } - } - - /* At this point TrueTypeFont is constructed, now need to verify the font format - and read the basic font properties */ - - /* The following tables are absolutely required: - * maxp, head, glyf, loca, name, cmap - */ - - if (!(getTable(t, O_maxp) && getTable(t, O_head) && getTable(t, O_glyf) && getTable(t, O_loca) && getTable(t, O_name) && getTable(t, O_cmap) )) { - CloseTTFont(t); - return SF_TTFORMAT; - } - - table = getTable(t, O_maxp); - t->nglyphs = GetUInt16(table, 4, 1); - - table = getTable(t, O_head); - t->unitsPerEm = GetUInt16(table, 18, 1); - indexfmt = GetInt16(table, 50, 1); - - if( ((indexfmt != 0) && (indexfmt != 1)) || (t->unitsPerEm <= 0) ) { - CloseTTFont(t); - return SF_TTFORMAT; - } - - k = (getTableSize(t, O_loca) / (indexfmt ? 4 : 2)) - 1; - if (k < (int)t->nglyphs) t->nglyphs = k; /* Hack for broken Chinese fonts */ - - table = getTable(t, O_loca); - - t->goffsets = (sal_uInt32 *) calloc(1+t->nglyphs, sizeof(sal_uInt32)); - assert(t->goffsets != 0); - - for (i = 0; i <= (int)t->nglyphs; i++) { - t->goffsets[i] = indexfmt ? GetUInt32(table, i << 2, 1) : (sal_uInt32)GetUInt16(table, i << 1, 1) << 1; - } - - table = getTable(t, O_hhea); - t->numberOfHMetrics = (table != 0) ? GetUInt16(table, 34, 1) : 0; - - table = getTable(t, O_vhea); - t->numOfLongVerMetrics = (table != 0) ? GetUInt16(table, 34, 1) : 0; - - GetNames(t); - FindCmap(t); - GetKern(t); - ReadGSUB( t, 0, 0 ); - - return SF_OK; -} - -void CloseTTFont(TrueTypeFont *ttf) /*FOLD01*/ -{ - if (ttf->tag != TTFontClassTag) return; - -#if !defined(WIN32) && !defined(OS2) - if( ttf->fname ) - munmap((char *) ttf->ptr, ttf->fsize); -#endif - free(ttf->fname); - free(ttf->goffsets); - free(ttf->psname); - free(ttf->family); - if( ttf->ufamily ) - free( ttf->ufamily ); - free(ttf->subfamily); - if( ttf->usubfamily ) - free( ttf->usubfamily ); - free(ttf->tables); - free(ttf->tlens); - free(ttf->kerntables); - - ReleaseGSUB(ttf); - - free(ttf); - return; -} - -int GetTTGlyphPoints(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray) -{ - return GetTTGlyphOutline(ttf, glyphID, pointArray, 0, 0); -} - -#ifdef NO_LIST -static -#endif -int GetTTGlyphComponents(TrueTypeFont *ttf, sal_uInt32 glyphID, list glyphlist) -{ - sal_uInt8 *ptr, *glyf = getTable(ttf, O_glyf); - int n = 1; - - if (glyphID >= ttf->nglyphs) return 0; - ptr = glyf + ttf->goffsets[glyphID]; - - listAppend(glyphlist, (void *) (sal_IntPtr) glyphID); - - if (GetInt16(ptr, 0, 1) == -1) { - sal_uInt16 flags, index; - ptr += 10; - do { - flags = GetUInt16(ptr, 0, 1); - index = GetUInt16(ptr, 2, 1); - - ptr += 4; - n += GetTTGlyphComponents(ttf, index, glyphlist); - - if (flags & ARG_1_AND_2_ARE_WORDS) { - ptr += 4; - } else { - ptr += 2; - } - - if (flags & WE_HAVE_A_SCALE) { - ptr += 2; - } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) { - ptr += 4; - } else if (flags & WE_HAVE_A_TWO_BY_TWO) { - ptr += 8; - } - } while (flags & MORE_COMPONENTS); - } - - return n; -} - -#ifndef NO_TYPE3 -int CreateT3FromTTGlyphs(TrueTypeFont *ttf, FILE *outf, const char *fname, /*FOLD00*/ - sal_uInt16 *glyphArray, sal_uInt8 *encoding, int nGlyphs, - int wmode) -{ - ControlPoint *pa; - PSPathElement *path; - int i, j, r, n; - sal_uInt8 *table = getTable(ttf, O_head); - TTGlyphMetrics metrics; - int UPEm = ttf->unitsPerEm; - - const char *h01 = "%%!PS-AdobeFont-%d.%d-%d.%d\n"; - const char *h02 = "%% Creator: %s %s %s\n"; - const char *h09 = "%% Original font name: %s\n"; - - const char *h10 = - "30 dict begin\n" - "/PaintType 0 def\n" - "/FontType 3 def\n" - "/StrokeWidth 0 def\n"; - - const char *h11 = "/FontName (%s) cvn def\n"; - - /* - const char *h12 = "%/UniqueID %d def\n"; - */ - const char *h13 = "/FontMatrix [.001 0 0 .001 0 0] def\n"; - const char *h14 = "/FontBBox [%d %d %d %d] def\n"; - - const char *h15= - "/Encoding 256 array def\n" - " 0 1 255 {Encoding exch /.notdef put} for\n"; - - const char *h16 = " Encoding %d /glyph%d put\n"; - const char *h17 = "/XUID [103 0 0 16#%08X %d 16#%08X 16#%08X] def\n"; - - const char *h30 = "/CharProcs %d dict def\n"; - const char *h31 = " CharProcs begin\n"; - const char *h32 = " /.notdef {} def\n"; - const char *h33 = " /glyph%d {\n"; - const char *h34 = " } bind def\n"; - const char *h35 = " end\n"; - - const char *h40 = - "/BuildGlyph {\n" - " exch /CharProcs get exch\n" - " 2 copy known not\n" - " {pop /.notdef} if\n" - " get exec\n" - "} bind def\n" - "/BuildChar {\n" - " 1 index /Encoding get exch get\n" - " 1 index /BuildGlyph get exec\n" - "} bind def\n" - "currentdict end\n"; - - const char *h41 = "(%s) cvn exch definefont pop\n"; - - - if (!((nGlyphs > 0) && (nGlyphs <= 256))) return SF_GLYPHNUM; - if (!glyphArray) return SF_BADARG; - if (!fname) fname = ttf->psname; - - fprintf(outf, h01, GetInt16(table, 0, 1), GetUInt16(table, 2, 1), GetInt16(table, 4, 1), GetUInt16(table, 6, 1)); - fprintf(outf, h02, modname, modver, modextra); - fprintf(outf, h09, ttf->psname); - - fprintf(outf, h10); - fprintf(outf, h11, fname); -/* fprintf(outf, h12, 4000000); */ - - /* XUID generation: - * 103 0 0 C1 C2 C3 C4 - * C1 - CRC-32 of the entire source TrueType font - * C2 - number of glyphs in the subset - * C3 - CRC-32 of the glyph array - * C4 - CRC-32 of the encoding array - * - * All CRC-32 numbers are presented as hexadecimal numbers - */ - - fprintf(outf, h17, rtl_crc32(0, ttf->ptr, ttf->fsize), nGlyphs, rtl_crc32(0, glyphArray, nGlyphs * 2), rtl_crc32(0, encoding, nGlyphs)); - fprintf(outf, h13); - fprintf(outf, h14, XUnits(UPEm, GetInt16(table, 36, 1)), XUnits(UPEm, GetInt16(table, 38, 1)), XUnits(UPEm, GetInt16(table, 40, 1)), XUnits(UPEm, GetInt16(table, 42, 1))); - fprintf(outf, h15); - - for (i = 0; i < nGlyphs; i++) { - fprintf(outf, h16, encoding[i], i); - } - - fprintf(outf, h30, nGlyphs+1); - fprintf(outf, h31); - fprintf(outf, h32); - - for (i = 0; i < nGlyphs; i++) { - fprintf(outf, h33, i); - r = GetTTGlyphOutline(ttf, glyphArray[i] < ttf->nglyphs ? glyphArray[i] : 0, &pa, &metrics, 0); - - if (r > 0) { - n = BSplineToPSPath(pa, r, &path); - } else { - n = 0; /* glyph might have zero contours but valid metrics ??? */ - path = 0; - if (r < 0) { /* glyph is not present in the font - pa array was not allocated, so no need to free it */ - continue; - } - } - fprintf(outf, "\t%d %d %d %d %d %d setcachedevice\n", - wmode == 0 ? XUnits(UPEm, metrics.aw) : 0, - wmode == 0 ? 0 : -XUnits(UPEm, metrics.ah), - XUnits(UPEm, metrics.xMin), - XUnits(UPEm, metrics.yMin), - XUnits(UPEm, metrics.xMax), - XUnits(UPEm, metrics.yMax)); - - for (j = 0; j < n; j++) { - switch (path[j].type) { - case PS_MOVETO: - fprintf(outf, "\t%d %d moveto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1)); - break; - - case PS_LINETO: - fprintf(outf, "\t%d %d lineto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1)); - break; - - case PS_CURVETO: - fprintf(outf, "\t%d %d %d %d %d %d curveto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1), XUnits(UPEm, path[j].x2), XUnits(UPEm, path[j].y2), XUnits(UPEm, path[j].x3), XUnits(UPEm, path[j].y3)); - break; - - case PS_CLOSEPATH: - fprintf(outf, "\tclosepath\n"); - break; - } - } - if (n > 0) fprintf(outf, "\tfill\n"); /* if glyph is not a whitespace character */ - - fprintf(outf, h34); - - free(pa); - free(path); - } - fprintf(outf, h35); - - fprintf(outf, h40); - fprintf(outf, h41, fname); - - return SF_OK; -} -#endif - -#ifndef NO_TTCR -int CreateTTFromTTGlyphs(TrueTypeFont *ttf, - const char *fname, - sal_uInt16 *glyphArray, - sal_uInt8 *encoding, - int nGlyphs, - int nNameRecs, - NameRecord *nr, - sal_uInt32 flags) -{ - TrueTypeCreator *ttcr; - TrueTypeTable *head=0, *hhea=0, *maxp=0, *cvt=0, *prep=0, *glyf=0, *fpgm=0, *cmap=0, *name=0, *post = 0, *os2 = 0; - sal_uInt8 *p; - int i; - int res; - sal_uInt32 *gID; - - TrueTypeCreatorNewEmpty(T_true, &ttcr); - - /** name **/ - - if (flags & TTCF_AutoName) { - /* not implemented yet - NameRecord *names; - NameRecord newname; - int n = GetTTNameRecords(ttf, &names); - int n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0, n6 = 0; - sal_uInt8 *cp1; - sal_uInt8 suffix[32]; - sal_uInt32 c1 = crc32(glyphArray, nGlyphs * 2); - sal_uInt32 c2 = crc32(encoding, nGlyphs); - int len; - snprintf(suffix, 31, "S%08X%08X-%d", c1, c2, nGlyphs); - - name = TrueTypeTableNew_name(0, 0); - for (i = 0; i < n; i++) { - if (names[i].platformID == 1 && names[i].encodingID == 0 && names[i].languageID == 0 && names[i].nameID == 1) { - - memcpy(newname, names+i, sizeof(NameRecord)); - newname.slen = name[i].slen + strlen(suffix); - */ - const sal_uInt8 ptr[] = {0,'T',0,'r',0,'u',0,'e',0,'T',0,'y',0,'p',0,'e',0,'S',0,'u',0,'b',0,'s',0,'e',0,'t'}; - NameRecord n1 = {1, 0, 0, 6, 14, (sal_uInt8*)"TrueTypeSubset"}; - NameRecord n2 = {3, 1, 1033, 6, 28, 0}; - n2.sptr = (sal_uInt8 *) ptr; - name = TrueTypeTableNew_name(0, 0); - nameAdd(name, &n1); - nameAdd(name, &n2); - } else { - if (nNameRecs == 0) { - NameRecord *names; - int n = GetTTNameRecords(ttf, &names); - name = TrueTypeTableNew_name(n, names); - DisposeNameRecords(names, n); - } else { - name = TrueTypeTableNew_name(nNameRecs, nr); - } - } - - /** maxp **/ - maxp = TrueTypeTableNew_maxp(getTable(ttf, O_maxp), getTableSize(ttf, O_maxp)); - - /** hhea **/ - p = getTable(ttf, O_hhea); - if (p) { - hhea = TrueTypeTableNew_hhea(GetUInt16(p, 4, 1), GetUInt16(p, 6, 1), GetUInt16(p, 8, 1), GetUInt16(p, 18, 1), GetUInt16(p, 20, 1)); - } else { - hhea = TrueTypeTableNew_hhea(0, 0, 0, 0, 0); - } - - /** head **/ - - p = getTable(ttf, O_head); - assert(p != 0); - head = TrueTypeTableNew_head(GetUInt32(p, 4, 1), - GetUInt16(p, 16, 1), - GetUInt16(p, 18, 1), - p+20, - GetUInt16(p, 44, 1), - GetUInt16(p, 46, 1), - GetInt16(p, 48, 1)); - - - /** glyf **/ - - glyf = TrueTypeTableNew_glyf(); - gID = scalloc(nGlyphs, sizeof(sal_uInt32)); - - for (i = 0; i < nGlyphs; i++) { - gID[i] = glyfAdd(glyf, GetTTRawGlyphData(ttf, glyphArray[i]), ttf); - } - - /** cmap **/ - cmap = TrueTypeTableNew_cmap(); - - for (i=0; i < nGlyphs; i++) { - cmapAdd(cmap, 0x010000, encoding[i], gID[i]); - } - - /** cvt **/ - if ((p = getTable(ttf, O_cvt)) != 0) { - cvt = TrueTypeTableNew(T_cvt, getTableSize(ttf, O_cvt), p); - } - - /** prep **/ - if ((p = getTable(ttf, O_prep)) != 0) { - prep = TrueTypeTableNew(T_prep, getTableSize(ttf, O_prep), p); - } - - /** fpgm **/ - if ((p = getTable(ttf, O_fpgm)) != 0) { - fpgm = TrueTypeTableNew(T_fpgm, getTableSize(ttf, O_fpgm), p); - } - - /** post **/ - if ((p = getTable(ttf, O_post)) != 0) { - post = TrueTypeTableNew_post(0x00030000, - GetUInt32(p, 4, 1), - GetUInt16(p, 8, 1), - GetUInt16(p, 10, 1), - GetUInt16(p, 12, 1)); - } else { - post = TrueTypeTableNew_post(0x00030000, 0, 0, 0, 0); - } - - if (flags & TTCF_IncludeOS2) { - if ((p = getTable(ttf, O_OS2)) != 0) { - os2 = TrueTypeTableNew(T_OS2, getTableSize(ttf, O_OS2), p); - } - } - - AddTable(ttcr, name); AddTable(ttcr, maxp); AddTable(ttcr, hhea); - AddTable(ttcr, head); AddTable(ttcr, glyf); AddTable(ttcr, cmap); - AddTable(ttcr, cvt ); AddTable(ttcr, prep); AddTable(ttcr, fpgm); - AddTable(ttcr, post); AddTable(ttcr, os2); - - if ((res = StreamToFile(ttcr, fname)) != SF_OK) { -#if OSL_DEBUG_LEVEL > 1 - fprintf(stderr, "StreamToFile: error code: %d.\n", res); -#endif - } - - TrueTypeCreatorDispose(ttcr); - free(gID); - - return res; -} -#endif - - -#ifndef NO_TYPE42 -static GlyphOffsets *GlyphOffsetsNew(sal_uInt8 *sfntP) -{ - GlyphOffsets *res = smalloc(sizeof(GlyphOffsets)); - sal_uInt8 *loca = NULL; - sal_uInt16 i, numTables = GetUInt16(sfntP, 4, 1); - sal_uInt32 locaLen = 0; - sal_Int16 indexToLocFormat = 0; - - for (i = 0; i < numTables; i++) { - sal_uInt32 tag = GetUInt32(sfntP + 12, 16 * i, 1); - sal_uInt32 off = GetUInt32(sfntP + 12, 16 * i + 8, 1); - sal_uInt32 len = GetUInt32(sfntP + 12, 16 * i + 12, 1); - - if (tag == T_loca) { - loca = sfntP + off; - locaLen = len; - } else if (tag == T_head) { - indexToLocFormat = GetInt16(sfntP + off, 50, 1); - } - } - - res->nGlyphs = locaLen / ((indexToLocFormat == 1) ? 4 : 2); - assert(res->nGlyphs != 0); - res->offs = scalloc(res->nGlyphs, sizeof(sal_uInt32)); - - for (i = 0; i < res->nGlyphs; i++) { - if (indexToLocFormat == 1) { - res->offs[i] = GetUInt32(loca, i * 4, 1); - } else { - res->offs[i] = GetUInt16(loca, i * 2, 1) << 1; - } - } - return res; -} - -static void GlyphOffsetsDispose(GlyphOffsets *_this) -{ - if (_this) { - free(_this->offs); - free(_this); - } -} - -static void DumpSfnts(FILE *outf, sal_uInt8 *sfntP) -{ - HexFmt *h = HexFmtNew(outf); - sal_uInt16 i, numTables = GetUInt16(sfntP, 4, 1); - sal_uInt32 j, *offs, *len; - GlyphOffsets *go = GlyphOffsetsNew(sfntP); - sal_uInt8 pad[] = {0,0,0,0}; /* zeroes */ - - assert(numTables <= 9); /* Type42 has 9 required tables */ - - offs = scalloc(numTables, sizeof(sal_uInt32)); - len = scalloc(numTables, sizeof(sal_uInt32)); - - fputs("/sfnts [", outf); - HexFmtOpenString(h); - HexFmtBlockWrite(h, sfntP, 12); /* stream out the Offset Table */ - HexFmtBlockWrite(h, sfntP+12, 16 * numTables); /* stream out the Table Directory */ - - for (i=0; i<numTables; i++) { - sal_uInt32 tag = GetUInt32(sfntP + 12, 16 * i, 1); - sal_uInt32 off = GetUInt32(sfntP + 12, 16 * i + 8, 1); - sal_uInt32 len = GetUInt32(sfntP + 12, 16 * i + 12, 1); - - if (tag != T_glyf) { - HexFmtBlockWrite(h, sfntP + off, len); - } else { - sal_uInt8 *glyf = sfntP + off; - sal_uInt32 o, l; - for (j = 0; j < go->nGlyphs - 1; j++) { - o = go->offs[j]; - l = go->offs[j + 1] - o; - HexFmtBlockWrite(h, glyf + o, l); - } - } - HexFmtBlockWrite(h, pad, (4 - (len & 3)) & 3); - } - HexFmtCloseString(h); - fputs("] def\n", outf); - GlyphOffsetsDispose(go); - HexFmtDispose(h); - free(offs); - free(len); -} - -int CreateT42FromTTGlyphs(TrueTypeFont *ttf, - FILE *outf, - const char *psname, - sal_uInt16 *glyphArray, - sal_uInt8 *encoding, - int nGlyphs) -{ - TrueTypeCreator *ttcr; - TrueTypeTable *head=0, *hhea=0, *maxp=0, *cvt=0, *prep=0, *glyf=0, *fpgm=0; - sal_uInt8 *p; - int i; - int res; - - sal_uInt32 ver, rev; - sal_uInt8 *headP; - - sal_uInt8 *sfntP; - sal_uInt32 sfntLen; - int UPEm = ttf->unitsPerEm; - - sal_uInt16 *gID; - - if (nGlyphs >= 256) return SF_GLYPHNUM; - - assert(psname != 0); - - TrueTypeCreatorNewEmpty(T_true, &ttcr); - - /* head */ - headP = p = getTable(ttf, O_head); - assert(p != 0); - head = TrueTypeTableNew_head(GetUInt32(p, 4, 1), GetUInt16(p, 16, 1), GetUInt16(p, 18, 1), p+20, GetUInt16(p, 44, 1), GetUInt16(p, 46, 1), GetInt16(p, 48, 1)); - ver = GetUInt32(p, 0, 1); - rev = GetUInt32(p, 4, 1); - - /** hhea **/ - p = getTable(ttf, O_hhea); - if (p) { - hhea = TrueTypeTableNew_hhea(GetUInt16(p, 4, 1), GetUInt16(p, 6, 1), GetUInt16(p, 8, 1), GetUInt16(p, 18, 1), GetUInt16(p, 20, 1)); - } else { - hhea = TrueTypeTableNew_hhea(0, 0, 0, 0, 0); - } - - /** maxp **/ - maxp = TrueTypeTableNew_maxp(getTable(ttf, O_maxp), getTableSize(ttf, O_maxp)); - - /** cvt **/ - if ((p = getTable(ttf, O_cvt)) != 0) { - cvt = TrueTypeTableNew(T_cvt, getTableSize(ttf, O_cvt), p); - } - - /** prep **/ - if ((p = getTable(ttf, O_prep)) != 0) { - prep = TrueTypeTableNew(T_prep, getTableSize(ttf, O_prep), p); - } - - /** fpgm **/ - if ((p = getTable(ttf, O_fpgm)) != 0) { - fpgm = TrueTypeTableNew(T_fpgm, getTableSize(ttf, O_fpgm), p); - } - - /** glyf **/ - glyf = TrueTypeTableNew_glyf(); - gID = scalloc(nGlyphs, sizeof(sal_uInt32)); - - for (i = 0; i < nGlyphs; i++) { - gID[i] = (sal_uInt16)glyfAdd(glyf, GetTTRawGlyphData(ttf, glyphArray[i]), ttf); - } - - AddTable(ttcr, head); AddTable(ttcr, hhea); AddTable(ttcr, maxp); AddTable(ttcr, cvt); - AddTable(ttcr, prep); AddTable(ttcr, glyf); AddTable(ttcr, fpgm); - - if ((res = StreamToMemory(ttcr, &sfntP, &sfntLen)) != SF_OK) { - TrueTypeCreatorDispose(ttcr); - free(gID); - return res; - } - - fprintf(outf, "%%!PS-TrueTypeFont-%d.%d-%d.%d\n", (int)(ver>>16), (int)(ver & 0xFFFF), (int)(rev>>16), (int)(rev & 0xFFFF)); - fprintf(outf, "%%%%Creator: %s %s %s\n", modname, modver, modextra); - fprintf(outf, "%%- Font subset generated from a source font file: '%s'\n", ttf->fname); - fprintf(outf, "%%- Original font name: %s\n", ttf->psname); - fprintf(outf, "%%- Original font family: %s\n", ttf->family); - fprintf(outf, "%%- Original font sub-family: %s\n", ttf->subfamily); - fprintf(outf, "11 dict begin\n"); - fprintf(outf, "/FontName (%s) cvn def\n", psname); - fprintf(outf, "/PaintType 0 def\n"); - fprintf(outf, "/FontMatrix [1 0 0 1 0 0] def\n"); - fprintf(outf, "/FontBBox [%d %d %d %d] def\n", XUnits(UPEm, GetInt16(headP, 36, 1)), XUnits(UPEm, GetInt16(headP, 38, 1)), XUnits(UPEm, GetInt16(headP, 40, 1)), XUnits(UPEm, GetInt16(headP, 42, 1))); - fprintf(outf, "/FontType 42 def\n"); - fprintf(outf, "/Encoding 256 array def\n"); - fprintf(outf, " 0 1 255 {Encoding exch /.notdef put} for\n"); - - for (i = 1; i<nGlyphs; i++) { - fprintf(outf, "Encoding %d /glyph%d put\n", encoding[i], gID[i]); - } - fprintf(outf, "/XUID [103 0 1 16#%08X %d 16#%08X 16#%08X] def\n", (unsigned int)rtl_crc32(0, ttf->ptr, ttf->fsize), (unsigned int)nGlyphs, (unsigned int)rtl_crc32(0, glyphArray, nGlyphs * 2), (unsigned int)rtl_crc32(0, encoding, nGlyphs)); - - DumpSfnts(outf, sfntP); - - /* dump charstrings */ - fprintf(outf, "/CharStrings %d dict dup begin\n", nGlyphs); - fprintf(outf, "/.notdef 0 def\n"); - for (i = 1; i < (int)glyfCount(glyf); i++) { - fprintf(outf,"/glyph%d %d def\n", i, i); - } - fprintf(outf, "end readonly def\n"); - - fprintf(outf, "FontName currentdict end definefont pop\n"); - TrueTypeCreatorDispose(ttcr); - free(gID); - free(sfntP); - return SF_OK; -} -#endif - - -#ifndef NO_MAPPERS -int MapString(TrueTypeFont *ttf, sal_uInt16 *str, int nchars, sal_uInt16 *glyphArray, int bvertical) -{ - int i; - sal_uInt16 *cp; - - if (ttf->cmapType == CMAP_NOT_USABLE ) return -1; - if (!nchars) return 0; - - if (glyphArray == 0) { - cp = str; - } else { - cp = glyphArray; - } - - switch (ttf->cmapType) { - case CMAP_MS_Symbol: - if( ttf->mapper == getGlyph0 ) { - sal_uInt16 aChar; - for( i = 0; i < nchars; i++ ) { - aChar = str[i]; - if( ( aChar & 0xf000 ) == 0xf000 ) - aChar &= 0x00ff; - cp[i] = aChar; - } - } - else if( glyphArray ) - memcpy(glyphArray, str, nchars * 2); - break; - - case CMAP_MS_Unicode: - if (glyphArray != 0) { - memcpy(glyphArray, str, nchars * 2); - } - break; - - case CMAP_MS_ShiftJIS: TranslateString12(str, cp, nchars); break; - case CMAP_MS_Big5: TranslateString13(str, cp, nchars); break; - case CMAP_MS_PRC: TranslateString14(str, cp, nchars); break; - case CMAP_MS_Wansung: TranslateString15(str, cp, nchars); break; - case CMAP_MS_Johab: TranslateString16(str, cp, nchars); break; - } - - for (i = 0; i < nchars; i++) { - cp[i] = (sal_uInt16)ttf->mapper(ttf->cmap, cp[i]); - if (cp[i]!=0 && bvertical!=0) - cp[i] = (sal_uInt16)UseGSUB(ttf,cp[i],bvertical); - } - return nchars; -} - -sal_uInt16 MapChar(TrueTypeFont *ttf, sal_uInt16 ch, int bvertical) -{ - switch (ttf->cmapType) { - case CMAP_MS_Symbol: - - if( ttf->mapper == getGlyph0 && ( ch & 0xf000 ) == 0xf000 ) - ch &= 0x00ff; - return (sal_uInt16)ttf->mapper(ttf->cmap, ch ); - - case CMAP_MS_Unicode: break; - case CMAP_MS_ShiftJIS: ch = TranslateChar12(ch); break; - case CMAP_MS_Big5: ch = TranslateChar13(ch); break; - case CMAP_MS_PRC: ch = TranslateChar14(ch); break; - case CMAP_MS_Wansung: ch = TranslateChar15(ch); break; - case CMAP_MS_Johab: ch = TranslateChar16(ch); break; - default: return 0; - } - ch = (sal_uInt16)ttf->mapper(ttf->cmap, ch); - if (ch!=0 && bvertical!=0) - ch = (sal_uInt16)UseGSUB(ttf,ch,bvertical); - return ch; -} - -int DoesVerticalSubstitution( TrueTypeFont *ttf, int bvertical) -{ - int nRet = 0; - if( bvertical) - nRet = HasVerticalGSUB( ttf); - return nRet; -} - -#endif - -int GetTTGlyphCount( TrueTypeFont* ttf ) -{ - return ttf->nglyphs; -} - -TTSimpleGlyphMetrics *GetTTSimpleGlyphMetrics(TrueTypeFont *ttf, sal_uInt16 *glyphArray, int nGlyphs, int mode) -{ - sal_uInt8* pTable; - TTSimpleGlyphMetrics *res; - int i; - sal_uInt16 glyphID; - sal_uInt32 n; - int UPEm = ttf->unitsPerEm; - int nTableSize; - - if (mode == 0) { - n = ttf->numberOfHMetrics; - pTable = getTable( ttf, O_hmtx ); - nTableSize = getTableSize( ttf, O_hmtx ); - } else { - n = ttf->numOfLongVerMetrics; - pTable = getTable( ttf, O_vmtx ); - nTableSize = getTableSize( ttf, O_vmtx ); - } - - if (!nGlyphs || !glyphArray) return 0; /* invalid parameters */ - if (!n || !pTable) return 0; /* the font does not contain the requested metrics */ - - res = calloc(nGlyphs, sizeof(TTSimpleGlyphMetrics)); - assert(res != 0); - - for (i=0; i<nGlyphs; i++) { - int nAdvOffset, nLsbOffset; - glyphID = glyphArray[i]; - - if (glyphID < n) { - nAdvOffset = 4 * glyphID; - nLsbOffset = nAdvOffset + 2; - } else { - nAdvOffset = 4 * (n - 1); - if( glyphID < ttf->nglyphs ) - nLsbOffset = 4 * n + 2 * (glyphID - n); - else /* font is broken -> use lsb of last hmetrics */ - nLsbOffset = nAdvOffset + 2; - } - - if( nAdvOffset >= nTableSize) - res[i].adv = 0; /* better than a crash for buggy fonts */ - else - res[i].adv = SAL_INT_CAST( - sal_uInt16, - XUnits( UPEm, GetUInt16( pTable, nAdvOffset, 1) ) ); - - if( nLsbOffset >= nTableSize) - res[i].sb = 0; /* better than a crash for buggy fonts */ - else - res[i].sb = SAL_INT_CAST( - sal_Int16, - XUnits( UPEm, GetInt16( pTable, nLsbOffset, 1) ) ); - } - - return res; -} - -#ifndef NO_MAPPERS -TTSimpleGlyphMetrics *GetTTSimpleCharMetrics(TrueTypeFont * ttf, sal_uInt16 firstChar, int nChars, int mode) -{ - TTSimpleGlyphMetrics *res = 0; - sal_uInt16 *str; - int i, n; - - str = malloc(nChars * 2); - assert(str != 0); - - for (i=0; i<nChars; i++) str[i] = (sal_uInt16)(firstChar + i); - if ((n = MapString(ttf, str, nChars, 0, mode)) != -1) { - res = GetTTSimpleGlyphMetrics(ttf, str, n, mode); - } - - free(str); - - return res; -} -#endif - -void GetTTGlobalFontInfo(TrueTypeFont *ttf, TTGlobalFontInfo *info) -{ - sal_uInt8 *table; - int UPEm = ttf->unitsPerEm; - - memset(info, 0, sizeof(TTGlobalFontInfo)); - - info->family = ttf->family; - info->ufamily = ttf->ufamily; - info->subfamily = ttf->subfamily; - info->usubfamily = ttf->usubfamily; - info->psname = ttf->psname; - info->symbolEncoded = (ttf->cmapType == CMAP_MS_Symbol); - - table = getTable(ttf, O_OS2); - if (table) { - info->weight = GetUInt16(table, 4, 1); - info->width = GetUInt16(table, 6, 1); - - /* There are 3 different versions of OS/2 table: original (68 bytes long), - * Microsoft old (78 bytes long) and Microsoft new (86 bytes long,) - * Apple's documentation recommends looking at the table length. - */ - if (getTableSize(ttf, O_OS2) > 68) { - info->typoAscender = XUnits(UPEm,GetInt16(table, 68, 1)); - info->typoDescender = XUnits(UPEm, GetInt16(table, 70, 1)); - info->typoLineGap = XUnits(UPEm, GetInt16(table, 72, 1)); - info->winAscent = XUnits(UPEm, GetUInt16(table, 74, 1)); - info->winDescent = XUnits(UPEm, GetUInt16(table, 76, 1)); - /* sanity check; some fonts treat winDescent as signed - * violating the standard */ - if( info->winDescent > 5*UPEm ) - info->winDescent = XUnits(UPEm, GetInt16(table, 76,1)); - } - if (ttf->cmapType == CMAP_MS_Unicode) { - info->rangeFlag = 1; - info->ur1 = GetUInt32(table, 42, 1); - info->ur2 = GetUInt32(table, 46, 1); - info->ur3 = GetUInt32(table, 50, 1); - info->ur4 = GetUInt32(table, 54, 1); - } - memcpy(info->panose, table + 32, 10); - info->typeFlags = GetUInt16( table, 8, 1 ); - } - - table = getTable(ttf, O_post); - if (table) { - info->pitch = GetUInt32(table, 12, 1); - info->italicAngle = GetInt32(table, 4, 1); - } - - table = getTable(ttf, O_head); /* 'head' tables is always there */ - info->xMin = XUnits(UPEm, GetInt16(table, 36, 1)); - info->yMin = XUnits(UPEm, GetInt16(table, 38, 1)); - info->xMax = XUnits(UPEm, GetInt16(table, 40, 1)); - info->yMax = XUnits(UPEm, GetInt16(table, 42, 1)); - info->macStyle = GetInt16(table, 44, 1); - - table = getTable(ttf, O_hhea); - if (table) { - info->ascender = XUnits(UPEm, GetInt16(table, 4, 1)); - info->descender = XUnits(UPEm, GetInt16(table, 6, 1)); - info->linegap = XUnits(UPEm, GetInt16(table, 8, 1)); - } - - table = getTable(ttf, O_vhea); - if (table) { - info->vascent = XUnits(UPEm, GetInt16(table, 4, 1)); - info->vdescent = XUnits(UPEm, GetInt16(table, 6, 1)); - } -} - -#ifdef TEST5 -void KernGlyphs(TrueTypeFont *ttf, sal_uInt16 *glyphs, int nglyphs, int wmode, KernData *kern) -{ - int i; - - if (!nglyphs || !glyphs || !kern) return; - - for (i = 0; i < nglyphs-1; i++) kern[i].x = kern[i].y = 0; - - switch (ttf->kerntype) { - case KT_APPLE_NEW: KernGlyphsPrim1(ttf, glyphs, nglyphs, wmode, kern); return; - case KT_MICROSOFT: KernGlyphsPrim2(ttf, glyphs, nglyphs, wmode, kern); return; - default: return; - } -} -#endif - -GlyphData *GetTTRawGlyphData(TrueTypeFont *ttf, sal_uInt32 glyphID) -{ - sal_uInt8 *glyf = getTable(ttf, O_glyf); - sal_uInt8 *hmtx = getTable(ttf, O_hmtx); - sal_uInt32 length; - GlyphData *d; - ControlPoint *cp; - int i, n, m; - - if( glyphID >= ttf->nglyphs ) - return 0; - - /* #127161# check the glyph offsets */ - length = getTableSize( ttf, O_glyf ); - if( length < ttf->goffsets[ glyphID+1 ] ) - return 0; - - length = ttf->goffsets[glyphID+1] - ttf->goffsets[glyphID]; - - d = malloc(sizeof(GlyphData)); assert(d != 0); - - if (length > 0) { - sal_uInt8 *srcptr = glyf + ttf->goffsets[glyphID]; - d->ptr = malloc((length + 1) & ~1); assert(d->ptr != 0); - memcpy( d->ptr, srcptr, length ); - d->compflag = (GetInt16( srcptr, 0, 1 ) < 0); - } else { - d->ptr = 0; - d->compflag = 0; - } - - d->glyphID = glyphID; - d->nbytes = (sal_uInt16)((length + 1) & ~1); - - /* now calculate npoints and ncontours */ - n = GetTTGlyphPoints(ttf, glyphID, &cp); - if (n != -1) { - m = 0; - for (i = 0; i < n; i++) { - if (cp[i].flags & 0x8000) m++; - } - d->npoints = (sal_uInt16)n; - d->ncontours = (sal_uInt16)m; - free(cp); - } else { - d->npoints = 0; - d->ncontours = 0; - } - - /* get advance width and left sidebearing */ - if (glyphID < ttf->numberOfHMetrics) { - d->aw = GetUInt16(hmtx, 4 * glyphID, 1); - d->lsb = GetInt16(hmtx, 4 * glyphID + 2, 1); - } else { - d->aw = GetUInt16(hmtx, 4 * (ttf->numberOfHMetrics - 1), 1); - d->lsb = GetInt16(hmtx + ttf->numberOfHMetrics * 4, (glyphID - ttf->numberOfHMetrics) * 2, 1); - } - - return d; -} - -int GetTTNameRecords(TrueTypeFont *ttf, NameRecord **nr) -{ - sal_uInt8 *table = getTable(ttf, O_name); - int nTableSize = getTableSize(ttf, O_name ); - sal_uInt16 n = GetUInt16(table, 2, 1); - sal_uInt8* rec_string = NULL; - int nStrBase = GetUInt16(table, 4, 1); - NameRecord *rec; - int i; - - *nr = 0; - if (n == 0) return 0; - - rec = calloc(n, sizeof(NameRecord)); - - for (i = 0; i < n; i++) { - int nStrOffset = GetUInt16(table + 6, 10 + 12 * i, 1); - rec[i].platformID = GetUInt16(table + 6, 12 * i, 1); - rec[i].encodingID = GetUInt16(table + 6, 2 + 12 * i, 1); - rec[i].languageID = GetUInt16(table + 6, 4 + 12 * i, 1); - rec[i].nameID = GetUInt16(table + 6, 6 + 12 * i, 1); - rec[i].slen = GetUInt16(table + 6, 8 + 12 * i, 1); - if (rec[i].slen) { - if( nStrBase+nStrOffset+rec[i].slen >= nTableSize ) { - rec[i].sptr = 0; - rec[i].slen = 0; - continue; - } - - rec_string = table + nStrBase + nStrOffset; - // sanity check - if( rec_string > (sal_uInt8*)ttf->ptr && rec_string < ((sal_uInt8*)ttf->ptr + ttf->fsize - rec[i].slen ) ) - { - rec[i].sptr = (sal_uInt8 *) malloc(rec[i].slen); assert(rec[i].sptr != 0); - memcpy(rec[i].sptr, rec_string, rec[i].slen); - } - else - { -#ifdef DEBUG - fprintf( stderr, "found invalid name record %d with name id %d for file %s\n", - i, rec[i].nameID, ttf->fname ); -#endif - rec[i].sptr = 0; - rec[i].slen = 0; - } - } else { - rec[i].sptr = 0; - } - // some fonts have 3.0 names => fix them to 3.1 - if( (rec[i].platformID == 3) && (rec[i].encodingID == 0) ) - rec[i].encodingID = 1; - } - - *nr = rec; - return n; -} - -void DisposeNameRecords(NameRecord* nr, int n) -{ - int i; - for (i = 0; i < n; i++) { - if (nr[i].sptr) free(nr[i].sptr); - } - free(nr); -} - - - - -#ifdef TEST1 -/* This example creates a subset of a TrueType font with two encoded characters */ -int main(int ac, char **av) -{ - TrueTypeFont *fnt; - int r; - - /* Array of Unicode source characters */ - sal_uInt16 chars[2]; - - /* Encoding vector maps character encoding to the ordinal number - * of the glyph in the output file */ - sal_uInt8 encoding[2]; - - /* This array is for glyph IDs that source characters map to */ - sal_uInt16 g[2]; - - - if (ac < 2) return 0; - - if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { - fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); - return 0; - } - - - /* We want to create the output file that only contains two Unicode characters: - * L'a' and L'A' */ - - chars[0] = L'a'; - chars[1] = L'A'; - - /* Figure out what glyphs do these characters map in our font */ - MapString(fnt, chars, 2, g); - - /* Encode the characters. Value of encoding[i] is the number 0..255 which maps to glyph i of the - * newly generated font */ - encoding[0] = chars[0]; - encoding[1] = chars[1]; - - - /* Generate a subset */ - CreateT3FromTTGlyphs(fnt, stdout, 0, g, encoding, 2, 0); - - /* Now call the dtor for the font */ - CloseTTFont(fnt); - return 0; -} -#endif - -#ifdef TEST2 -/* This example extracts first 224 glyphs from a TT fonts and encodes them starting at 32 */ -int main(int ac, char **av) -{ - TrueTypeFont *fnt; - int i, r; - - /* Array of Unicode source characters */ - sal_uInt16 glyphs[224]; - - /* Encoding vector maps character encoding to the ordinal number - * of the glyph in the output file */ - sal_uInt8 encoding[224]; - - - - for (i=0; i<224; i++) { - glyphs[i] = i; - encoding[i] = 32 + i; - } - - if (ac < 2) return 0; - - if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { - fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); - return 0; - } - - - /* Encode the characters. Value of encoding[i] is the number 0..255 which maps to glyph i of the - * newly generated font */ - - /* Generate a subset */ - CreateT3FromTTGlyphs(fnt, stdout, 0, glyphs, encoding, 224, 0); - - /* Now call the dtor for the font */ - CloseTTFont(fnt); - return 0; -} -#endif - -#ifdef TEST3 -/* Glyph metrics example */ -int main(int ac, char **av) -{ - TrueTypeFont *fnt; - int i, r; - sal_uInt16 glyphs[224]; - TTSimpleGlyphMetrics *m; - - for (i=0; i<224; i++) { - glyphs[i] = i; - } - - if (ac < 2) return 0; - - if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { - fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); - return 0; - } - - if ((m = GetTTSimpleGlyphMetrics(fnt, glyphs, 224, 0)) == 0) { - printf("Requested metrics is not available\n"); - } else { - for (i=0; i<224; i++) { - printf("%d. advWid: %5d, LSBear: %5d\n", i, m[i].adv, m[i].sb); - } - } - - /* Now call the dtor for the font */ - free(m); - CloseTTFont(fnt); - return 0; -} -#endif - -#ifdef TEST4 -int main(int ac, char **av) -{ - TrueTypeFont *fnt; - TTGlobalFontInfo info; - int i, r; - - - if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { - fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); - return 0; - } - - printf("Font file: %s\n", av[1]); - -#ifdef PRINT_KERN - switch (fnt->kerntype) { - case KT_MICROSOFT: - printf("\tkern: MICROSOFT, ntables: %d.", fnt->nkern); - if (fnt->nkern) { - printf(" ["); - for (i=0; i<fnt->nkern; i++) { - printf("%04X ", GetUInt16(fnt->kerntables[i], 4, 1)); - } - printf("]"); - } - printf("\n"); - break; - - case KT_APPLE_NEW: - printf("\tkern: APPLE_NEW, ntables: %d.", fnt->nkern); - if (fnt->nkern) { - printf(" ["); - for (i=0; i<fnt->nkern; i++) { - printf("%04X ", GetUInt16(fnt->kerntables[i], 4, 1)); - } - printf("]"); - } - printf("\n"); - break; - - case KT_NONE: - printf("\tkern: none.\n"); - break; - - default: - printf("\tkern: unrecoginzed.\n"); - break; - } - printf("\n"); -#endif - - GetTTGlobalFontInfo(fnt, &info); - printf("\tfamily name: `%s`\n", info.family); - printf("\tsubfamily name: `%s`\n", info.subfamily); - printf("\tpostscript name: `%s`\n", info.psname); - printf("\tweight: %d\n", info.weight); - printf("\twidth: %d\n", info.width); - printf("\tpitch: %d\n", info.pitch); - printf("\titalic angle: %d\n", info.italicAngle); - printf("\tbouding box: [%d %d %d %d]\n", info.xMin, info.yMin, info.xMax, info.yMax); - printf("\tascender: %d\n", info.ascender); - printf("\tdescender: %d\n", info.descender); - printf("\tlinegap: %d\n", info.linegap); - printf("\tvascent: %d\n", info.vascent); - printf("\tvdescent: %d\n", info.vdescent); - printf("\ttypoAscender: %d\n", info.typoAscender); - printf("\ttypoDescender: %d\n", info.typoDescender); - printf("\ttypoLineGap: %d\n", info.typoLineGap); - printf("\twinAscent: %d\n", info.winAscent); - printf("\twinDescent: %d\n", info.winDescent); - printf("\tUnicode ranges:\n"); - for (i = 0; i < 32; i++) { - if ((info.ur1 >> i) & 1) { - printf("\t\t\t%s\n", UnicodeRangeName(i)); - } - } - for (i = 0; i < 32; i++) { - if ((info.ur2 >> i) & 1) { - printf("\t\t\t%s\n", UnicodeRangeName(i+32)); - } - } - for (i = 0; i < 32; i++) { - if ((info.ur3 >> i) & 1) { - printf("\t\t\t%s\n", UnicodeRangeName(i+64)); - } - } - for (i = 0; i < 32; i++) { - if ((info.ur4 >> i) & 1) { - printf("\t\t\t%s\n", UnicodeRangeName(i+96)); - } - } - - CloseTTFont(fnt); - return 0; -} -#endif - -#ifdef TEST5 -/* Kerning example */ -int main(int ac, char **av) -{ - TrueTypeFont *fnt; - sal_uInt16 g[224]; - KernData d[223]; - int r, i, k = 0; - - g[k++] = 11; - g[k++] = 36; - g[k++] = 11; - g[k++] = 98; - g[k++] = 11; - g[k++] = 144; - g[k++] = 41; - g[k++] = 171; - g[k++] = 51; - g[k++] = 15; - - if (ac < 2) return 0; - - if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { - fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); - return 0; - } - - KernGlyphs(fnt, g, k, 0, d); - - for (i = 0; i < k-1; i++) { - printf("%3d %3d: [%3d %3d]\n", g[i], g[i+1], d[i].x, d[i].y); - } - - CloseTTFont(fnt); - return 0; -} -#endif - - - -#ifdef TEST6 -/* This example extracts a single glyph from a font */ -int main(int ac, char **av) -{ - TrueTypeFont *fnt; - int r, i; - - sal_uInt16 glyphs[256]; - sal_uInt8 encoding[256]; - - for (i=0; i<256; i++) { - glyphs[i] = 512 + i; - encoding[i] = i; - } - -#if 0 - i=0; - glyphs[i++] = 2001; - glyphs[i++] = 2002; - glyphs[i++] = 2003; - glyphs[i++] = 2004; - glyphs[i++] = 2005; - glyphs[i++] = 2006; - glyphs[i++] = 2007; - glyphs[i++] = 2008; - glyphs[i++] = 2009; - glyphs[i++] = 2010; - glyphs[i++] = 2011; - glyphs[i++] = 2012; - glyphs[i++] = 2013; - glyphs[i++] = 2014; - glyphs[i++] = 2015; - glyphs[i++] = 2016; - glyphs[i++] = 2017; - glyphs[i++] = 2018; - glyphs[i++] = 2019; - glyphs[i++] = 2020; - - - r = 97; - i = 0; - encoding[i++] = r++; - encoding[i++] = r++; - encoding[i++] = r++; - encoding[i++] = r++; - encoding[i++] = r++; - encoding[i++] = r++; - encoding[i++] = r++; - encoding[i++] = r++; - encoding[i++] = r++; - encoding[i++] = r++; - encoding[i++] = r++; - encoding[i++] = r++; - encoding[i++] = r++; - encoding[i++] = r++; - encoding[i++] = r++; - encoding[i++] = r++; - encoding[i++] = r++; - encoding[i++] = r++; - encoding[i++] = r++; - encoding[i++] = r++; -#endif - - if (ac < 2) return 0; - - if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { - fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); - return 0; - } - - /* Generate a subset */ - CreateT3FromTTGlyphs(fnt, stdout, 0, glyphs, encoding, 256, 0); - - fprintf(stderr, "UnitsPerEm: %d.\n", fnt->unitsPerEm); - - /* Now call the dtor for the font */ - CloseTTFont(fnt); - return 0; -} -#endif - -#ifdef TEST7 -/* NameRecord extraction example */ -int main(int ac, char **av) -{ - TrueTypeFont *fnt; - int r, i, j, n; - NameRecord *nr; - - if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { - fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); - return 0; - } - - if ((n = GetTTNameRecords(fnt, &nr)) == 0) { - fprintf(stderr, "No name records in the font.\n"); - return 0; - } - - printf("Number of name records: %d.\n", n); - for (i = 0; i < n; i++) { - printf("%d %d %04X %d [", nr[i].platformID, nr[i].encodingID, nr[i].languageID, nr[i].nameID); - for (j=0; j<nr[i].slen; j++) { - printf("%c", isprint(nr[i].sptr[j]) ? nr[i].sptr[j] : '.'); - } - printf("]\n"); - } - - - DisposeNameRecords(nr, n); - CloseTTFont(fnt); - return 0; -} -#endif - -#ifdef TEST8 -/* TrueType -> TrueType subsetting */ -int main(int ac, char **av) -{ - TrueTypeFont *fnt; - sal_uInt16 glyphArray[] = { 0, 98, 99, 22, 24, 25, 26, 27, 28, 29, 30, 31, 1270, 1289, 34}; - sal_uInt8 encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}; - int r; - - if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { - fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); - return 0; - } - - CreateTTFromTTGlyphs(fnt, "subfont.ttf", glyphArray, encoding, 15, 0, 0, TTCF_AutoName | TTCF_IncludeOS2); - - - CloseTTFont(fnt); - - return 0; -} -#endif - -#ifdef TEST9 -/* TrueType -> Type42 subsetting */ -int main(int ac, char **av) -{ - TrueTypeFont *fnt; - /* - sal_uInt16 glyphArray[] = { 0, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34}; - sal_uInt8 encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}; - */ - sal_uInt16 glyphArray[] = { 0, 6711, 6724, 11133, 11144, 14360, 26, 27, 28, 29, 30, 31, 1270, 1289, 34}; - sal_uInt8 encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}; - int r; - - if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { - fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); - return 0; - } - - CreateT42FromTTGlyphs(fnt, stdout, "testfont", glyphArray, encoding, 15); - - CloseTTFont(fnt); - - return 0; -} -#endif - -#ifdef TEST10 -/* Component glyph test */ -int main(int ac, char **av) -{ - TrueTypeFont *fnt; - int r, i; - list glyphlist = listNewEmpty(); - - - if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { - fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); - return 0; - } - - for (i = 0; i < fnt->nglyphs; i++) { - r = GetTTGlyphComponents(fnt, i, glyphlist); - if (r > 1) { - printf("%d -> ", i); - listToFirst(glyphlist); - do { - printf("%d ", (int) listCurrent(glyphlist)); - } while (listNext(glyphlist)); - printf("\n"); - } else { - printf("%d: single glyph.\n", i); - } - listClear(glyphlist); - } - - CloseTTFont(fnt); - listDispose(glyphlist); - - return 0; -} -#endif - - diff --git a/vcl/source/fontsubset/sft.cxx b/vcl/source/fontsubset/sft.cxx new file mode 100644 index 000000000000..6723e01b97f1 --- /dev/null +++ b/vcl/source/fontsubset/sft.cxx @@ -0,0 +1,3312 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +/* + * Sun Font Tools + * + * Author: Alexander Gelfenbain + * + */ + +#if OSL_DEBUG_LEVEL == 0 +# ifndef NDEBUG +# define NDEBUG +# endif +#endif +#include <assert.h> + +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#ifdef UNX +#include <sys/mman.h> +#include <sys/stat.h> +#endif +#include "sft.hxx" +#include "gsub.h" +#if ! (defined(NO_TTCR) && defined(NO_TYPE42)) +#include "ttcr.hxx" +#endif +#ifndef NO_MAPPERS /* include MapChar() and MapString() */ +#include "xlat.hxx" +#endif +#ifndef NO_TYPE3 /* include CreateT3FromTTGlyphs() */ +#include <rtl/crc.h> +#endif + +#include <osl/endian.h> +#include <algorithm> + +#ifdef TEST7 +#include <ctype.h> +#endif + +namespace vcl +{ + +/*- module identification */ + +static const char *modname = "SunTypeTools-TT"; +static const char *modver = "1.0"; +static const char *modextra = "gelf"; + +/*- private functions, constants and data types */ /*FOLD00*/ + +enum PathSegmentType { + PS_NOOP = 0, + PS_MOVETO = 1, + PS_LINETO = 2, + PS_CURVETO = 3, + PS_CLOSEPATH = 4 +}; + +struct PSPathElement +{ + PathSegmentType type; + int x1, y1; + int x2, y2; + int x3, y3; + + PSPathElement( PathSegmentType i_eType ) : type( i_eType ), + x1( 0 ), y1( 0 ), + x2( 0 ), y2( 0 ), + x3( 0 ), y3( 0 ) + { + } +}; + +/*- In horisontal writing mode right sidebearing is calculated using this formula + *- rsb = aw - (lsb + xMax - xMin) -*/ +typedef struct { + sal_Int16 xMin; + sal_Int16 yMin; + sal_Int16 xMax; + sal_Int16 yMax; + sal_uInt16 aw; /*- Advance Width (horisontal writing mode) */ + sal_Int16 lsb; /*- Left sidebearing (horisontal writing mode) */ + sal_uInt16 ah; /*- advance height (vertical writing mode) */ + sal_Int16 tsb; /*- top sidebearing (vertical writing mode) */ +} TTGlyphMetrics; + +#define HFORMAT_LINELEN 64 + +typedef struct { + FILE *o; + char buffer[HFORMAT_LINELEN]; + int bufpos; + int total; +} HexFmt; + +typedef struct { + sal_uInt32 nGlyphs; /* number of glyphs in the font + 1 */ + sal_uInt32 *offs; /* array of nGlyphs offsets */ +} GlyphOffsets; + +/* private tags */ +static const sal_uInt32 TTFontClassTag = 0x74746663; /* 'ttfc' */ + +static const sal_uInt32 T_true = 0x74727565; /* 'true' */ +static const sal_uInt32 T_ttcf = 0x74746366; /* 'ttcf' */ + +/* standard TrueType table tags */ +#define T_maxp 0x6D617870 +#define T_glyf 0x676C7966 +#define T_head 0x68656164 +#define T_loca 0x6C6F6361 +#define T_name 0x6E616D65 +#define T_hhea 0x68686561 +#define T_hmtx 0x686D7478 +#define T_cmap 0x636D6170 +#define T_vhea 0x76686561 +#define T_vmtx 0x766D7478 +#define T_OS2 0x4F532F32 +#define T_post 0x706F7374 +#define T_kern 0x6B65726E +#define T_cvt 0x63767420 +#define T_prep 0x70726570 +#define T_fpgm 0x6670676D +#define T_gsub 0x47535542 + +#define LAST_URANGE_BIT 69 +const char *ulcodes[LAST_URANGE_BIT+2] = { + /* 0 */ "Basic Latin", + /* 1 */ "Latin-1 Supplement", + /* 2 */ "Latin Extended-A", + /* 3 */ "Latin Extended-B", + /* 4 */ "IPA Extensions", + /* 5 */ "Spacing Modifier Letters", + /* 6 */ "Combining Diacritical Marks", + /* 7 */ "Basic Greek", + /* 8 */ "Greek Symbols And Coptic", + /* 9 */ "Cyrillic", + /* 10 */ "Armenian", + /* 11 */ "Basic Hebrew", + /* 12 */ "Hebrew Extended (A and B blocks combined)", + /* 13 */ "Basic Arabic", + /* 14 */ "Arabic Extended", + /* 15 */ "Devanagari", + /* 16 */ "Bengali", + /* 17 */ "Gurmukhi", + /* 18 */ "Gujarati", + /* 19 */ "Oriya", + /* 20 */ "Tamil", + /* 21 */ "Telugu", + /* 22 */ "Kannada", + /* 23 */ "Malayalam", + /* 24 */ "Thai", + /* 25 */ "Lao", + /* 26 */ "Basic Georgian", + /* 27 */ "Georgian Extended", + /* 28 */ "Hangul Jamo", + /* 29 */ "Latin Extended Additional", + /* 30 */ "Greek Extended", + /* 31 */ "General Punctuation", + /* 32 */ "Superscripts And Subscripts", + /* 33 */ "Currency Symbols", + /* 34 */ "Combining Diacritical Marks For Symbols", + /* 35 */ "Letterlike Symbols", + /* 36 */ "Number Forms", + /* 37 */ "Arrows", + /* 38 */ "Mathematical Operators", + /* 39 */ "Miscellaneous Technical", + /* 40 */ "Control Pictures", + /* 41 */ "Optical Character Recognition", + /* 42 */ "Enclosed Alphanumerics", + /* 43 */ "Box Drawing", + /* 44 */ "Block Elements", + /* 45 */ "Geometric Shapes", + /* 46 */ "Miscellaneous Symbols", + /* 47 */ "Dingbats", + /* 48 */ "CJK Symbols And Punctuation", + /* 49 */ "Hiragana", + /* 50 */ "Katakana", + /* 51 */ "Bopomofo", + /* 52 */ "Hangul Compatibility Jamo", + /* 53 */ "CJK Miscellaneous", + /* 54 */ "Enclosed CJK Letters And Months", + /* 55 */ "CJK Compatibility", + /* 56 */ "Hangul", + /* 57 */ "Reserved for Unicode SubRanges", + /* 58 */ "Reserved for Unicode SubRanges", + /* 59 */ "CJK Unified Ideographs", + /* 60 */ "Private Use Area", + /* 61 */ "CJK Compatibility Ideographs", + /* 62 */ "Alphabetic Presentation Forms", + /* 63 */ "Arabic Presentation Forms-A", + /* 64 */ "Combining Half Marks", + /* 65 */ "CJK Compatibility Forms", + /* 66 */ "Small Form Variants", + /* 67 */ "Arabic Presentation Forms-B", + /* 68 */ "Halfwidth And Fullwidth Forms", + /* 69 */ "Specials", + /*70-127*/ "Reserved for Unicode SubRanges" +}; + + + +/*- inline functions */ /*FOLD01*/ +#ifdef __GNUC__ +#define _inline static __inline__ +#else +#define _inline static +#endif + +_inline void *smalloc(size_t size) +{ + void *res = malloc(size); + assert(res != 0); + return res; +} + +_inline void *scalloc(size_t n, size_t size) +{ + void *res = calloc(n, size); + assert(res != 0); + return res; +} + +_inline sal_uInt32 mkTag(sal_uInt8 a, sal_uInt8 b, sal_uInt8 c, sal_uInt8 d) { + return (a << 24) | (b << 16) | (c << 8) | d; +} + +/*- Data access macros for data stored in big-endian or little-endian format */ +_inline sal_Int16 GetInt16(const sal_uInt8 *ptr, size_t offset, int bigendian) +{ + sal_Int16 t; + assert(ptr != 0); + + if (bigendian) { + t = (ptr+offset)[0] << 8 | (ptr+offset)[1]; + } else { + t = (ptr+offset)[1] << 8 | (ptr+offset)[0]; + } + + return t; +} + +_inline sal_uInt16 GetUInt16(const sal_uInt8 *ptr, size_t offset, int bigendian) +{ + sal_uInt16 t; + assert(ptr != 0); + + if (bigendian) { + t = (ptr+offset)[0] << 8 | (ptr+offset)[1]; + } else { + t = (ptr+offset)[1] << 8 | (ptr+offset)[0]; + } + + return t; +} + +_inline sal_Int32 GetInt32(const sal_uInt8 *ptr, size_t offset, int bigendian) +{ + sal_Int32 t; + assert(ptr != 0); + + if (bigendian) { + t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 | + (ptr+offset)[2] << 8 | (ptr+offset)[3]; + } else { + t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 | + (ptr+offset)[1] << 8 | (ptr+offset)[0]; + } + + return t; +} + +_inline sal_uInt32 GetUInt32(const sal_uInt8 *ptr, size_t offset, int bigendian) +{ + sal_uInt32 t; + assert(ptr != 0); + + + if (bigendian) { + t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 | + (ptr+offset)[2] << 8 | (ptr+offset)[3]; + } else { + t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 | + (ptr+offset)[1] << 8 | (ptr+offset)[0]; + } + + return t; +} + +_inline void PutInt16(sal_Int16 val, sal_uInt8 *ptr, size_t offset, int bigendian) +{ + assert(ptr != 0); + + if (bigendian) { + ptr[offset] = (sal_uInt8)((val >> 8) & 0xFF); + ptr[offset+1] = (sal_uInt8)(val & 0xFF); + } else { + ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF); + ptr[offset] = (sal_uInt8)(val & 0xFF); + } + +} + +#if defined(OSL_BIG_ENDIAN) +#define Int16FromMOTA(a) (a) +#define Int32FromMOTA(a) (a) +#else +static sal_uInt16 Int16FromMOTA(sal_uInt16 a) { + return (sal_uInt16) (((sal_uInt8)((a) >> 8)) | ((sal_uInt8)(a) << 8)); +} +static sal_uInt32 Int32FromMOTA(sal_uInt32 a) { + return ((a>>24)&0xFF) | (((a>>8)&0xFF00) | ((a&0xFF00)<<8) | ((a&0xFF)<<24)); +} +#endif + +_inline F16Dot16 fixedMul(F16Dot16 a, F16Dot16 b) +{ + unsigned int a1, b1; + unsigned int a2, b2; + F16Dot16 res; + int sign; + + sign = (a & 0x80000000) ^ (b & 0x80000000); + if (a < 0) a = -a; + if (b < 0) b = -b; + + a1 = a >> 16; + b1 = a & 0xFFFF; + a2 = b >> 16; + b2 = b & 0xFFFF; + + res = a1 * a2; + + /* if (res > 0x7FFF) assert(!"fixedMul: F16Dot16 overflow"); */ + + res <<= 16; + res += a1 * b2 + b1 * a2 + ((b1 * b2) >> 16); + + return sign ? -res : res; +} + + +_inline F16Dot16 fixedDiv(F16Dot16 a, F16Dot16 b) +{ + unsigned int f, r; + F16Dot16 res; + int sign; + + sign = (a & 0x80000000) ^ (b & 0x80000000); + if (a < 0) a = -a; + if (b < 0) b = -b; + + f = a / b; + r = a % b; + + /* if (f > 0x7FFFF) assert(!"fixedDiv: F16Dot16 overflow"); */ + + while (r > 0xFFFF) { + r >>= 1; + b >>= 1; + } + + res = (f << 16) + (r << 16) / b; + + return sign ? -res : res; +} + +/*- returns a * b / c -*/ +/* XXX provide a real implementation that preserves accuracy */ +_inline F16Dot16 fixedMulDiv(F16Dot16 a, F16Dot16 b, F16Dot16 c) +{ + F16Dot16 res; + + res = fixedMul(a, b); + return fixedDiv(res, c); +} + +/*- Translate units from TT to PS (standard 1/1000) -*/ +_inline int XUnits(int unitsPerEm, int n) +{ + return (n * 1000) / unitsPerEm; +} + +_inline const char *UnicodeRangeName(sal_uInt16 bit) +{ + if (bit > LAST_URANGE_BIT) bit = LAST_URANGE_BIT+1; + + return ulcodes[bit]; +} + +_inline sal_uInt8 *getTable(TrueTypeFont *ttf, sal_uInt32 ord) +{ + return (sal_uInt8*)ttf->tables[ord]; +} + +_inline sal_uInt32 getTableSize(TrueTypeFont *ttf, sal_uInt32 ord) +{ + return ttf->tlens[ord]; +} + +#ifndef NO_TYPE42 +/* Hex Formatter functions */ +static char HexChars[] = "0123456789ABCDEF"; + +static HexFmt *HexFmtNew(FILE *outf) +{ + HexFmt* res = (HexFmt*)smalloc(sizeof(HexFmt)); + res->bufpos = res->total = 0; + res->o = outf; + return res; +} + +static void HexFmtFlush(HexFmt *_this) +{ + if (_this->bufpos) { + fwrite(_this->buffer, 1, _this->bufpos, _this->o); + _this->bufpos = 0; + } +} + + +_inline void HexFmtOpenString(HexFmt *_this) +{ + fputs("<\n", _this->o); +} + +_inline void HexFmtCloseString(HexFmt *_this) +{ + HexFmtFlush(_this); + fputs("00\n>\n", _this->o); +} + +_inline void HexFmtDispose(HexFmt *_this) +{ + HexFmtFlush(_this); + free(_this); +} + +static void HexFmtBlockWrite(HexFmt *_this, const void *ptr, sal_uInt32 size) +{ + sal_uInt8 Ch; + sal_uInt32 i; + + if (_this->total + size > 65534) { + HexFmtFlush(_this); + HexFmtCloseString(_this); + _this->total = 0; + HexFmtOpenString(_this); + } + for (i=0; i<size; i++) { + Ch = ((sal_uInt8 *) ptr)[i]; + _this->buffer[_this->bufpos++] = HexChars[Ch >> 4]; + _this->buffer[_this->bufpos++] = HexChars[Ch & 0xF]; + if (_this->bufpos == HFORMAT_LINELEN) { + HexFmtFlush(_this); + fputc('\n', _this->o); + } + + } + _this->total += size; +} +#endif + + + +/* Outline Extraction functions */ /*FOLD01*/ + +/* fills the aw and lsb entries of the TTGlyphMetrics structure from hmtx table -*/ +static void GetMetrics(TrueTypeFont *ttf, sal_uInt32 glyphID, TTGlyphMetrics *metrics) +{ + sal_uInt8 *table = getTable(ttf, O_hmtx); + + metrics->aw = metrics->lsb = metrics->ah = metrics->tsb = 0; + if (!table || !ttf->numberOfHMetrics) return; + + if (glyphID < ttf->numberOfHMetrics) { + metrics->aw = GetUInt16(table, 4 * glyphID, 1); + metrics->lsb = GetInt16(table, 4 * glyphID + 2, 1); + } else { + metrics->aw = GetUInt16(table, 4 * (ttf->numberOfHMetrics - 1), 1); + metrics->lsb = GetInt16(table + ttf->numberOfHMetrics * 4, (glyphID - ttf->numberOfHMetrics) * 2, 1); + } + + table = getTable(ttf, O_vmtx); + if (!table || !ttf->numOfLongVerMetrics) return; + + if (glyphID < ttf->numOfLongVerMetrics) { + metrics->ah = GetUInt16(table, 4 * glyphID, 1); + metrics->tsb = GetInt16(table, 4 * glyphID + 2, 1); + } else { + metrics->ah = GetUInt16(table, 4 * (ttf->numOfLongVerMetrics - 1), 1); + metrics->tsb = GetInt16(table + ttf->numOfLongVerMetrics * 4, (glyphID - ttf->numOfLongVerMetrics) * 2, 1); + } +} + +static int GetTTGlyphOutline(TrueTypeFont *, sal_uInt32 , ControlPoint **, TTGlyphMetrics *, std::vector< sal_uInt32 >* ); + +/* returns the number of control points, allocates the pointArray */ +static int GetSimpleTTOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics) /*FOLD02*/ +{ + sal_uInt8 *table = getTable(ttf, O_glyf); + sal_uInt8 *ptr, *p, flag, n; + sal_Int16 numberOfContours; + sal_uInt16 t, instLen, lastPoint=0; + int i, j, z; + + *pointArray = 0; + + /* printf("GetSimpleTTOutline(%d)\n", glyphID); */ + + if (glyphID >= ttf->nglyphs) return 0; /*- glyph is not present in the font */ + ptr = table + ttf->goffsets[glyphID]; + if ((numberOfContours = GetInt16(ptr, 0, 1)) <= 0) return 0; /*- glyph is not simple */ + + if (metrics) { /*- GetCompoundTTOutline() calls this function with NULL metrics -*/ + metrics->xMin = GetInt16(ptr, 2, 1); + metrics->yMin = GetInt16(ptr, 4, 1); + metrics->xMax = GetInt16(ptr, 6, 1); + metrics->yMax = GetInt16(ptr, 8, 1); + GetMetrics(ttf, glyphID, metrics); + } + + /* determine the last point and be extra safe about it. But probably this code is not needed */ + + for (i=0; i<numberOfContours; i++) { + if ((t = GetUInt16(ptr, 10+i*2, 1)) > lastPoint) lastPoint = t; + } + + instLen = GetUInt16(ptr, 10 + numberOfContours*2, 1); + p = ptr + 10 + 2 * numberOfContours + 2 + instLen; + ControlPoint* pa = (ControlPoint*)calloc(lastPoint+1, sizeof(ControlPoint)); + + i = 0; + while (i <= lastPoint) { + pa[i++].flags = (sal_uInt32) (flag = *p++); + if (flag & 8) { /*- repeat flag */ + n = *p++; + for (j=0; j<n; j++) { + if (i > lastPoint) { /*- if the font is really broken */ + free(pa); + return 0; + } + pa[i++].flags = flag; + } + } + } + + /*- Process the X coordinate */ + z = 0; + for (i = 0; i <= lastPoint; i++) { + if (pa[i].flags & 0x02) { + if (pa[i].flags & 0x10) { + z += (int) (*p++); + } else { + z -= (int) (*p++); + } + } else if ( !(pa[i].flags & 0x10)) { + z += GetInt16(p, 0, 1); + p += 2; + } + pa[i].x = (sal_Int16)z; + } + + /*- Process the Y coordinate */ + z = 0; + for (i = 0; i <= lastPoint; i++) { + if (pa[i].flags & 0x04) { + if (pa[i].flags & 0x20) { + z += *p++; + } else { + z -= *p++; + } + } else if ( !(pa[i].flags & 0x20)) { + z += GetInt16(p, 0, 1); + p += 2; + } + pa[i].y = (sal_Int16)z; + } + + for (i=0; i<numberOfContours; i++) { + pa[GetUInt16(ptr, 10 + i * 2, 1)].flags |= 0x00008000; /*- set the end contour flag */ + } + + *pointArray = pa; + return lastPoint + 1; +} + +static int GetCompoundTTOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, std::vector< sal_uInt32 >& glyphlist) /*FOLD02*/ +{ + sal_uInt16 flags, index; + sal_Int16 e, f, numberOfContours; + sal_uInt8 *table = getTable(ttf, O_glyf); + sal_uInt8 *ptr; + std::vector<ControlPoint> myPoints; + ControlPoint *nextComponent, *pa; + int i, np; + F16Dot16 a = 0x10000, b = 0, c = 0, d = 0x10000, m, n, abs1, abs2, abs3; + + *pointArray = 0; + /* printf("GetCompoundTTOutline(%d)\n", glyphID); */ + + if (glyphID >= ttf->nglyphs) { /*- incorrect glyphID */ + return 0; + } + ptr = table + ttf->goffsets[glyphID]; + if ((numberOfContours = GetInt16(ptr, 0, 1)) != -1) { /*- glyph is not compound */ + return 0; + } + + if (metrics) { + metrics->xMin = GetInt16(ptr, 2, 1); + metrics->yMin = GetInt16(ptr, 4, 1); + metrics->xMax = GetInt16(ptr, 6, 1); + metrics->yMax = GetInt16(ptr, 8, 1); + GetMetrics(ttf, glyphID, metrics); + } + + ptr += 10; + + do { + flags = GetUInt16(ptr, 0, 1); + /* printf("flags: 0x%X\n", flags); */ + index = GetUInt16(ptr, 2, 1); + ptr += 4; + + if( std::find( glyphlist.begin(), glyphlist.end(), index ) != glyphlist.end() ) + { +#if OSL_DEBUG_LEVEL > 1 + fprintf(stderr, "Endless loop found in a compound glyph.\n"); + fprintf(stderr, "%d -> ", index); + fprintf(stderr," ["); + for( std::vector< sal_uInt32 >::const_iterator it = glyphlist.begin(); + it != glpyhlist.end(); ++it ) + { + fprintf( stderr,"%d ", (int) *it ); + } + fprintf(stderr,"]\n"); + /**/ +#endif + } + + glyphlist.push_back( index ); + +#ifdef DEBUG2 + fprintf(stderr,"glyphlist: += %d\n", index); +#endif + + if ((np = GetTTGlyphOutline(ttf, index, &nextComponent, 0, &glyphlist)) == 0) + { + /* XXX that probably indicates a corrupted font */ +#if OSL_DEBUG_LEVEL > 1 + fprintf(stderr, "An empty compound!\n"); + /* assert(!"An empty compound"); */ +#endif + } + +#ifdef DEBUG2 + fprintf(stderr,"%d [", (int)glyphlist.size() ); + for( std::vector< sal_uInt32 >::const_iterator it = glyphlist.begin(); + it != glpyhlist.end(); ++it ) + { + fprintf( stderr,"%d ", (int) *it ); + } + fprintf(stderr, "]\n"); + if( ! glpyhlist.empty() ) + fprintf(stderr, "glyphlist: -= %d\n", (int) glyphlist.back()); + +#endif + if( ! glyphlist.empty() ) + glyphlist.pop_back(); + + if (flags & USE_MY_METRICS) { + if (metrics) GetMetrics(ttf, index, metrics); + } + + if (flags & ARG_1_AND_2_ARE_WORDS) { + e = GetInt16(ptr, 0, 1); + f = GetInt16(ptr, 2, 1); + /* printf("ARG_1_AND_2_ARE_WORDS: %d %d\n", e & 0xFFFF, f & 0xFFFF); */ + ptr += 4; + } else { + if (flags & ARGS_ARE_XY_VALUES) { /* args are signed */ + e = (sal_Int8) *ptr++; + f = (sal_Int8) *ptr++; + /* printf("ARGS_ARE_XY_VALUES: %d %d\n", e & 0xFF, f & 0xFF); */ + } else { /* args are unsigned */ + /* printf("!ARGS_ARE_XY_VALUES\n"); */ + e = *ptr++; + f = *ptr++; + } + + } + + a = d = 0x10000; + b = c = 0; + + if (flags & WE_HAVE_A_SCALE) { +#ifdef DEBUG2 + fprintf(stderr, "WE_HAVE_A_SCALE\n"); +#endif + a = GetInt16(ptr, 0, 1) << 2; + d = a; + ptr += 2; + } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) { +#ifdef DEBUG2 + fprintf(stderr, "WE_HAVE_AN_X_AND_Y_SCALE\n"); +#endif + a = GetInt16(ptr, 0, 1) << 2; + d = GetInt16(ptr, 2, 1) << 2; + ptr += 4; + } else if (flags & WE_HAVE_A_TWO_BY_TWO) { +#ifdef DEBUG2 + fprintf(stderr, "WE_HAVE_A_TWO_BY_TWO\n"); +#endif + a = GetInt16(ptr, 0, 1) << 2; + b = GetInt16(ptr, 2, 1) << 2; + c = GetInt16(ptr, 4, 1) << 2; + d = GetInt16(ptr, 6, 1) << 2; + ptr += 8; + } + + abs1 = (a < 0) ? -a : a; + abs2 = (b < 0) ? -b : b; + m = (abs1 > abs2) ? abs1 : abs2; + abs3 = abs1 - abs2; + if (abs3 < 0) abs3 = -abs3; + if (abs3 <= 33) m *= 2; + + abs1 = (c < 0) ? -c : c; + abs2 = (d < 0) ? -d : d; + n = (abs1 > abs2) ? abs1 : abs2; + abs3 = abs1 - abs2; + if (abs3 < 0) abs3 = -abs3; + if (abs3 <= 33) n *= 2; + + if (!ARGS_ARE_XY_VALUES) { /* match the points */ + assert(!"ARGS_ARE_XY_VALUES is not implemented!!!\n"); + } + +#ifdef DEBUG2 + fprintf(stderr, "a: %f, b: %f, c: %f, d: %f, e: %f, f: %f, m: %f, n: %f\n", + ((double) a) / 65536, + ((double) b) / 65536, + ((double) c) / 65536, + ((double) d) / 65536, + ((double) e) / 65536, + ((double) f) / 65536, + ((double) m) / 65536, + ((double) n) / 65536); +#endif + + for (i=0; i<np; i++) { + F16Dot16 t; + ControlPoint cp; + cp.flags = nextComponent[i].flags; + t = fixedMulDiv(a, nextComponent[i].x << 16, m) + fixedMulDiv(c, nextComponent[i].y << 16, m) + (e << 16); + cp.x = (sal_Int16)(fixedMul(t, m) >> 16); + t = fixedMulDiv(b, nextComponent[i].x << 16, n) + fixedMulDiv(d, nextComponent[i].y << 16, n) + (f << 16); + cp.y = (sal_Int16)(fixedMul(t, n) >> 16); + +#ifdef DEBUG2 + fprintf(stderr, "( %d %d ) -> ( %d %d )\n", nextComponent[i].x, nextComponent[i].y, cp.x, cp.y); +#endif + + myPoints.push_back( cp ); + } + + free(nextComponent); + + } while (flags & MORE_COMPONENTS); + + + + np = myPoints.size(); + + pa = (ControlPoint*)calloc(np, sizeof(ControlPoint)); + assert(pa != 0); + + memcpy( pa, &myPoints[0], np*sizeof(ControlPoint) ); + + *pointArray = pa; + return np; +} + +/* NOTE: GetTTGlyphOutline() returns -1 if the glyphID is incorrect, + * but Get{Simple|Compound}GlyphOutline returns 0 in such a case. + * + * NOTE: glyphlist is the stack of glyphs traversed while constructing + * a composite glyph. This is a safequard against endless recursion + * in corrupted fonts. + */ +static int GetTTGlyphOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, std::vector< sal_uInt32 >* glyphlist) +{ + sal_uInt8 *ptr, *table = getTable(ttf, O_glyf); + sal_Int16 numberOfContours; + int length; + int res; + *pointArray = 0; + + if (metrics) { + memset(metrics, 0, sizeof(TTGlyphMetrics)); /*- metrics is initialized to all zeroes */ + } + + if (glyphID >= ttf->nglyphs) return -1; /**/ + + ptr = table + ttf->goffsets[glyphID]; + length = ttf->goffsets[glyphID+1] - ttf->goffsets[glyphID]; + + if (length == 0) { /*- empty glyphs still have hmtx and vmtx metrics values */ + if (metrics) GetMetrics(ttf, glyphID, metrics); + return 0; + } + + numberOfContours = GetInt16(ptr, 0, 1); + + if (numberOfContours >= 0) + { + res=GetSimpleTTOutline(ttf, glyphID, pointArray, metrics); + } + else + { + std::vector< sal_uInt32 > aPrivList; + aPrivList.push_back( glyphID ); + res = GetCompoundTTOutline(ttf, glyphID, pointArray, metrics, glyphlist ? *glyphlist : aPrivList ); + } + +#ifdef DEBUG3 + { + int i; + FILE *out = fopen("points.dat", "a"); + assert(out != 0); + fprintf(out, "Glyph: %d\nPoints: %d\n", glyphID, res); + for (i=0; i<res; i++) { + fprintf(out, "%c ", ((*pointArray)[i].flags & 0x8000) ? 'X' : '.'); + fprintf(out, "%c ", ((*pointArray)[i].flags & 1) ? '+' : '-'); + fprintf(out, "%d %d\n", (*pointArray)[i].x, (*pointArray)[i].y); + } + fclose(out); + } +#endif + + return res; +} + +#ifndef NO_TYPE3 + +/*- returns the number of items in the path -*/ + +static int BSplineToPSPath(ControlPoint *srcA, int srcCount, PSPathElement **path) +{ + std::vector< PSPathElement > aPathList; + int nPathCount = 0; + PSPathElement p( PS_NOOP ); + + int x0 = 0, y0 = 0, x1 = 0, y1 = 0, x2, y2, curx, cury; + int lastOff = 0; /*- last point was off-contour */ + int scflag = 1; /*- start contour flag */ + int ecflag = 0; /*- end contour flag */ + int cp = 0; /*- current point */ + int StartContour = 0, EndContour = 1; + + *path = 0; + + /* if (srcCount > 0) for(;;) */ + while (srcCount > 0) { /*- srcCount does not get changed inside the loop. */ + if (scflag) { + int l = cp; + StartContour = cp; + while (!(srcA[l].flags & 0x8000)) l++; + EndContour = l; + if (StartContour == EndContour) { + if (cp + 1 < srcCount) { + cp++; + continue; + } else { + break; + } + } + p = PSPathElement(PS_MOVETO); + if (!(srcA[cp].flags & 1)) { + if (!(srcA[EndContour].flags & 1)) { + p.x1 = x0 = (srcA[cp].x + srcA[EndContour].x + 1) / 2; + p.y1 = y0 = (srcA[cp].y + srcA[EndContour].y + 1) / 2; + } else { + p.x1 = x0 = srcA[EndContour].x; + p.y1 = y0 = srcA[EndContour].y; + } + } else { + p.x1 = x0 = srcA[cp].x; + p.y1 = y0 = srcA[cp].y; + cp++; + } + aPathList.push_back( p ); + lastOff = 0; + scflag = 0; + } + + curx = srcA[cp].x; + cury = srcA[cp].y; + + if (srcA[cp].flags & 1) + { + if (lastOff) + { + p = PSPathElement(PS_CURVETO); + p.x1 = x0 + (2 * (x1 - x0) + 1) / 3; + p.y1 = y0 + (2 * (y1 - y0) + 1) / 3; + p.x2 = x1 + (curx - x1 + 1) / 3; + p.y2 = y1 + (cury - y1 + 1) / 3; + p.x3 = curx; + p.y3 = cury; + aPathList.push_back( p ); + } + else + { + if (!(x0 == curx && y0 == cury)) + { /* eliminate empty lines */ + p = PSPathElement(PS_LINETO); + p.x1 = curx; + p.y1 = cury; + aPathList.push_back( p ); + } + } + x0 = curx; y0 = cury; lastOff = 0; + } + else + { + if (lastOff) + { + x2 = (x1 + curx + 1) / 2; + y2 = (y1 + cury + 1) / 2; + p = PSPathElement(PS_CURVETO); + p.x1 = x0 + (2 * (x1 - x0) + 1) / 3; + p.y1 = y0 + (2 * (y1 - y0) + 1) / 3; + p.x2 = x1 + (x2 - x1 + 1) / 3; + p.y2 = y1 + (y2 - y1 + 1) / 3; + p.x3 = x2; + p.y3 = y2; + aPathList.push_back( p ); + x0 = x2; y0 = y2; + x1 = curx; y1 = cury; + } else { + x1 = curx; y1 = cury; + } + lastOff = true; + } + + if (ecflag) { + aPathList.push_back( PSPathElement(PS_CLOSEPATH) ); + scflag = 1; + ecflag = 0; + cp = EndContour + 1; + if (cp >= srcCount) break; + continue; + } + + + if (cp == EndContour) { + cp = StartContour; + ecflag = true; + } else { + cp++; + } + } + + if( (nPathCount = (int)aPathList.size()) > 0) + { + *path = (PSPathElement*)calloc(nPathCount, sizeof(PSPathElement)); + assert(*path != 0); + memcpy( *path, &aPathList[0], nPathCount * sizeof(PSPathElement) ); + } + + return nPathCount; +} + +#endif + +/*- Extracts a string from the name table and allocates memory for it -*/ + +static char *nameExtract(sal_uInt8 *name, int nTableSize, int n, int dbFlag, sal_uInt16** ucs2result ) +{ + int i; + char *res; + sal_uInt8 *ptr = name + GetUInt16(name, 4, 1) + GetUInt16(name + 6, 12 * n + 10, 1); + int len = GetUInt16(name+6, 12 * n + 8, 1); + + // sanity check + if( ! len || ptr >= (name+nTableSize-len) ) + { + if( ucs2result ) + *ucs2result = NULL; + return NULL; + } + + if( ucs2result ) + *ucs2result = NULL; + if (dbFlag) { + res = (char*)malloc(1 + len/2); + assert(res != 0); + for (i = 0; i < len/2; i++) res[i] = *(ptr + i * 2 + 1); + res[len/2] = 0; + if( ucs2result ) + { + *ucs2result = (sal_uInt16*)malloc( len+2 ); + for (i = 0; i < len/2; i++ ) (*ucs2result)[i] = GetUInt16( ptr, 2*i, 1 ); + (*ucs2result)[len/2] = 0; + } + } else { + res = (char*)malloc(1 + len); + assert(res != 0); + memcpy(res, ptr, len); + res[len] = 0; + } + + return res; +} + +static int findname(sal_uInt8 *name, sal_uInt16 n, sal_uInt16 platformID, sal_uInt16 encodingID, sal_uInt16 languageID, sal_uInt16 nameID) +{ + int l = 0, r = n-1, i; + sal_uInt32 t1, t2; + sal_uInt32 m1, m2; + + if (n == 0) return -1; + + m1 = (platformID << 16) | encodingID; + m2 = (languageID << 16) | nameID; + + do { + i = (l + r) >> 1; + t1 = GetUInt32(name + 6, i * 12 + 0, 1); + t2 = GetUInt32(name + 6, i * 12 + 4, 1); + + if (! ((m1 < t1) || ((m1 == t1) && (m2 < t2)))) l = i + 1; + if (! ((m1 > t1) || ((m1 == t1) && (m2 > t2)))) r = i - 1; + } while (l <= r); + + if (l - r == 2) { + return l - 1; + } + + return -1; +} + +/* XXX marlett.ttf uses (3, 0, 1033) instead of (3, 1, 1033) and does not have any Apple tables. + * Fix: if (3, 1, 1033) is not found - need to check for (3, 0, 1033) + * + * /d/fonts/ttzh_tw/Big5/Hanyi/ma6b5p uses (1, 0, 19) for English strings, instead of (1, 0, 0) + * and does not have (3, 1, 1033) + * Fix: if (1, 0, 0) and (3, 1, 1033) are not found need to look for (1, 0, *) - that will + * require a change in algorithm + * + * /d/fonts/fdltest/Korean/h2drrm has unsorted names and a an unknown (to me) Mac LanguageID, + * but (1, 0, 1042) strings usable + * Fix: change algorithm, and use (1, 0, *) if both standard Mac and MS strings are not found + */ + +static void GetNames(TrueTypeFont *t) +{ + sal_uInt8 *table = getTable(t, O_name); + int nTableSize = getTableSize(t, O_name); + + sal_uInt16 n = GetUInt16(table, 2, 1); + int i, r; + sal_Bool bPSNameOK = sal_True; + + /* #129743# simple sanity check for name table entry count */ + if( nTableSize <= n * 12 + 6 ) + n = 0; + + /* PostScript name: preferred Microsoft */ + t->psname = NULL; + if ((r = findname(table, n, 3, 1, 0x0409, 6)) != -1) + t->psname = nameExtract(table, nTableSize, r, 1, NULL); + if ( ! t->psname && (r = findname(table, n, 1, 0, 0, 6)) != -1) + t->psname = nameExtract(table, nTableSize, r, 0, NULL); + if ( ! t->psname && (r = findname(table, n, 3, 0, 0x0409, 6)) != -1) + { + // some symbol fonts like Marlett have a 3,0 name! + t->psname = nameExtract(table, nTableSize, r, 1, NULL); + } + if ( ! t->psname ) + { + if ( t->fname ) + { + char* pReverse = t->fname + strlen(t->fname); + /* take only last token of filename */ + while(pReverse != t->fname && *pReverse != '/') pReverse--; + if(*pReverse == '/') pReverse++; + t->psname = strdup(pReverse); + assert(t->psname != 0); + for (i=strlen(t->psname) - 1; i > 0; i--) + { + /*- Remove the suffix -*/ + if (t->psname[i] == '.' ) { + t->psname[i] = 0; + break; + } + } + } + else + t->psname = strdup( "Unknown" ); + } + + /* Font family and subfamily names: preferred Apple */ + t->family = NULL; + if ((r = findname(table, n, 0, 0, 0, 1)) != -1) + t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily); + if ( ! t->family && (r = findname(table, n, 3, 1, 0x0409, 1)) != -1) + t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily); + if ( ! t->family && (r = findname(table, n, 1, 0, 0, 1)) != -1) + t->family = nameExtract(table, nTableSize, r, 0, NULL); + if ( ! t->family && (r = findname(table, n, 3, 1, 0x0411, 1)) != -1) + t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily); + if ( ! t->family && (r = findname(table, n, 3, 0, 0x0409, 1)) != -1) + t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily); + if ( ! t->family ) + { + t->family = strdup(t->psname); + assert(t->family != 0); + } + + t->subfamily = NULL; + t->usubfamily = NULL; + if ((r = findname(table, n, 1, 0, 0, 2)) != -1) + t->subfamily = nameExtract(table, nTableSize, r, 0, &t->usubfamily); + if ( ! t->subfamily && (r = findname(table, n, 3, 1, 0x0409, 2)) != -1) + t->subfamily = nameExtract(table, nTableSize, r, 1, &t->usubfamily); + if ( ! t->subfamily ) + { + t->subfamily = strdup(""); + } + + /* #i60349# sanity check psname + * psname parctically has to be 7bit ascii and should not contains spaces + * there is a class of broken fonts which do not fullfill that at all, so let's try + * if the family name is 7bit ascii and take it instead if so + */ + /* check psname */ + for( i = 0; t->psname[i] != 0 && bPSNameOK; i++ ) + if( t->psname[ i ] < 33 || (t->psname[ i ] & 0x80) ) + bPSNameOK = sal_False; + if( bPSNameOK == sal_False ) + { + sal_Bool bReplace = sal_True; + /* check if family is a suitable replacement */ + if( t->ufamily && t->family ) + { + for( i = 0; t->ufamily[ i ] != 0 && bReplace; i++ ) + if( t->ufamily[ i ] < 33 || t->ufamily[ i ] > 127 ) + bReplace = sal_False; + if( bReplace ) + { + free( t->psname ); + t->psname = strdup( t->family ); + } + } + } +} + +enum cmapType { + CMAP_NOT_USABLE = -1, + CMAP_MS_Symbol = 10, + CMAP_MS_Unicode = 11, + CMAP_MS_ShiftJIS = 12, + CMAP_MS_Big5 = 13, + CMAP_MS_PRC = 14, + CMAP_MS_Wansung = 15, + CMAP_MS_Johab = 16 +}; + +#define MISSING_GLYPH_INDEX 0 + +/* + * getGlyph[0246]() functions and freinds are implemented by: + * @author Manpreet Singh + * getGlyph12() function and friends by: + * @author HDU + */ +static sal_uInt32 getGlyph0(const sal_uInt8* cmap, sal_uInt32 c) { + if (c <= 255) { + return *(cmap + 6 + c); + } else { + return MISSING_GLYPH_INDEX; + } +} + +typedef struct _subHeader2 { + sal_uInt16 firstCode; + sal_uInt16 entryCount; + sal_uInt16 idDelta; + sal_uInt16 idRangeOffset; +} subHeader2; + +static sal_uInt32 getGlyph2(const sal_uInt8 *cmap, sal_uInt32 c) { + sal_uInt16 *CMAP2 = (sal_uInt16 *) cmap; + sal_uInt8 theHighByte; + + sal_uInt8 theLowByte; + subHeader2* subHeader2s; + sal_uInt16* subHeader2Keys; + sal_uInt16 firstCode; + int k; + sal_uInt32 ToReturn; + + theHighByte = (sal_uInt8)((c >> 8) & 0x00ff); + theLowByte = (sal_uInt8)(c & 0x00ff); + subHeader2Keys = CMAP2 + 3; + subHeader2s = (subHeader2 *)(subHeader2Keys + 256); + k = Int16FromMOTA(subHeader2Keys[theHighByte]) / 8; + + if(k == 0) { + firstCode = Int16FromMOTA(subHeader2s[k].firstCode); + if(theLowByte >= firstCode && theLowByte < (firstCode + Int16FromMOTA(subHeader2s[k].entryCount))) { + return *((&(subHeader2s[0].idRangeOffset)) + + (Int16FromMOTA(subHeader2s[0].idRangeOffset)/2) /* + offset */ + + theLowByte /* + to_look */ + - Int16FromMOTA(subHeader2s[0].firstCode) + ); + } else { + return MISSING_GLYPH_INDEX; + } + } else if (k > 0) { + firstCode = Int16FromMOTA(subHeader2s[k].firstCode); + if(theLowByte >= firstCode && theLowByte < (firstCode + Int16FromMOTA(subHeader2s[k].entryCount))) { + ToReturn = *((&(subHeader2s[k].idRangeOffset)) + + (Int16FromMOTA(subHeader2s[k].idRangeOffset)/2) + + theLowByte - firstCode); + if(ToReturn == 0) { + return MISSING_GLYPH_INDEX; + } else { + ToReturn += Int16FromMOTA(subHeader2s[k].idDelta); + return (ToReturn & 0xFFFF); + } + } else { + return MISSING_GLYPH_INDEX; + } + } else { + return MISSING_GLYPH_INDEX; + } +} + +static sal_uInt32 getGlyph6(const sal_uInt8 *cmap, sal_uInt32 c) { + sal_uInt16 firstCode, lastCode, count; + sal_uInt16 *CMAP6 = (sal_uInt16 *) cmap; + + firstCode = Int16FromMOTA(*(CMAP6 + 3)); + count = Int16FromMOTA(*(CMAP6 + 4)); + lastCode = firstCode + count - 1; + if (c < firstCode || c > lastCode) { + return MISSING_GLYPH_INDEX; + } else { + return *((CMAP6 + 5)/*glyphIdArray*/ + (c - firstCode)); + } +} + +static sal_uInt16 GEbinsearch(sal_uInt16 *ar, sal_uInt16 length, sal_uInt16 toSearch) { + signed int low, mid, high, lastfound = 0xffff; + sal_uInt16 res; + if(length == (sal_uInt16)0 || length == (sal_uInt16)0xFFFF) { + return (sal_uInt16)0xFFFF; + } + low = 0; + high = length - 1; + while(high >= low) { + mid = (high + low)/2; + res = Int16FromMOTA(*(ar+mid)); + if(res >= toSearch) { + lastfound = mid; + high = --mid; + } else { + low = ++mid; + } + } + return (sal_uInt16)lastfound; +} + + +static sal_uInt32 getGlyph4(const sal_uInt8 *cmap, sal_uInt32 c) { + sal_uInt16 i; + int ToReturn; + sal_uInt16 segCount; + sal_uInt16 * startCode; + sal_uInt16 * endCode; + sal_uInt16 * idDelta; + /* sal_uInt16 * glyphIdArray; */ + sal_uInt16 * idRangeOffset; + sal_uInt16 * glyphIndexArray; + sal_uInt16 *CMAP4 = (sal_uInt16 *) cmap; + /* sal_uInt16 GEbinsearch(sal_uInt16 *ar, sal_uInt16 length, sal_uInt16 toSearch); */ + + segCount = Int16FromMOTA(*(CMAP4 + 3))/2; + endCode = CMAP4 + 7; + i = GEbinsearch(endCode, segCount, (sal_uInt16)c); + + if (i == (sal_uInt16) 0xFFFF) { + return MISSING_GLYPH_INDEX; + } + startCode = endCode + segCount + 1; + + if(Int16FromMOTA(startCode[i]) > c) { + return MISSING_GLYPH_INDEX; + } + idDelta = startCode + segCount; + idRangeOffset = idDelta + segCount; + glyphIndexArray = idRangeOffset + segCount; + + if(Int16FromMOTA(idRangeOffset[i]) != 0) { + c = Int16FromMOTA(*(&(idRangeOffset[i]) + (Int16FromMOTA(idRangeOffset[i])/2 + (c - Int16FromMOTA(startCode[i]))))); + } + + ToReturn = (Int16FromMOTA(idDelta[i]) + c) & 0xFFFF; + return ToReturn; +} + +static sal_uInt32 getGlyph12(const sal_uInt8 *pCmap, sal_uInt32 cChar) { + const sal_uInt32* pCMAP12 = (const sal_uInt32*)pCmap; + int nLength = Int32FromMOTA( pCMAP12[1] ); + int nGroups = Int32FromMOTA( pCMAP12[3] ); + int nLower = 0; + int nUpper = nGroups; + + if( nUpper > (nLength-16)/12 ) + nUpper = (nLength-16)/12; + + /* binary search in "segmented coverage" subtable */ + while( nLower < nUpper ) { + int nIndex = (nLower + nUpper) / 2; + const sal_uInt32* pEntry = &pCMAP12[ 4 + 3*nIndex ]; + sal_uInt32 cStart = Int32FromMOTA( pEntry[0] ); + sal_uInt32 cLast = Int32FromMOTA( pEntry[1] ); + if( cChar < cStart ) + nUpper = nIndex; + else if( cChar > cLast ) + nLower = nIndex + 1; + else { /* found matching entry! */ + sal_uInt32 nGlyph = Int32FromMOTA( pEntry[2] ); + nGlyph += cChar - cStart; + return nGlyph; + } + } + + return MISSING_GLYPH_INDEX; +} + + +static void FindCmap(TrueTypeFont *ttf) +{ + sal_uInt8 *table = getTable(ttf, O_cmap); + sal_uInt32 table_size = getTableSize(ttf, O_cmap); + sal_uInt16 ncmaps = GetUInt16(table, 2, 1); + unsigned int i; + sal_uInt32 ThreeZero = 0; /* MS Symbol */ + sal_uInt32 ThreeOne = 0; /* MS UCS-2 */ + sal_uInt32 ThreeTwo = 0; /* MS ShiftJIS */ + sal_uInt32 ThreeThree = 0; /* MS Big5 */ + sal_uInt32 ThreeFour = 0; /* MS PRC */ + sal_uInt32 ThreeFive = 0; /* MS Wansung */ + sal_uInt32 ThreeSix = 0; /* MS Johab */ + + for (i = 0; i < ncmaps; i++) { + sal_uInt32 offset; + sal_uInt16 pID, eID; + + /* sanity check, cmap entry must lie within table */ + if( i*8+4 > table_size ) + break; + + pID = GetUInt16(table, 4 + i * 8, 1); + eID = GetUInt16(table, 6 + i * 8, 1); + offset = GetUInt32(table, 8 + i * 8, 1); + + /* sanity check, cmap must lie within file */ + if( (table - ttf->ptr) + offset > (sal_uInt32)ttf->fsize ) + continue; + + /* Unicode tables in Apple fonts */ + if (pID == 0) { + ThreeOne = offset; break; + } + + if (pID == 3) { + switch (eID) { + case 0: ThreeZero = offset; break; + case 10: // UCS-4 + case 1: ThreeOne = offset; break; + case 2: ThreeTwo = offset; break; + case 3: ThreeThree = offset; break; + case 4: ThreeFour = offset; break; + case 5: ThreeFive = offset; break; + case 6: ThreeSix = offset; break; + } + } + } + + if (ThreeOne) { + ttf->cmapType = CMAP_MS_Unicode; + ttf->cmap = table + ThreeOne; + } else if (ThreeTwo) { + ttf->cmapType = CMAP_MS_ShiftJIS; + ttf->cmap = table + ThreeTwo; + } else if (ThreeThree) { + ttf->cmapType = CMAP_MS_Big5; + ttf->cmap = table + ThreeThree; + } else if (ThreeFour) { + ttf->cmapType = CMAP_MS_PRC; + ttf->cmap = table + ThreeFour; + } else if (ThreeFive) { + ttf->cmapType = CMAP_MS_Wansung; + ttf->cmap = table + ThreeFive; + } else if (ThreeSix) { + ttf->cmapType = CMAP_MS_Johab; + ttf->cmap = table + ThreeSix; + } else if (ThreeZero) { + ttf->cmapType = CMAP_MS_Symbol; + ttf->cmap = table + ThreeZero; + } else { + ttf->cmapType = CMAP_NOT_USABLE; + ttf->cmap = 0; + } + + if (ttf->cmapType != CMAP_NOT_USABLE) { + switch (GetUInt16(ttf->cmap, 0, 1)) { + case 0: ttf->mapper = getGlyph0; break; + case 2: ttf->mapper = getGlyph2; break; + case 4: ttf->mapper = getGlyph4; break; + case 6: ttf->mapper = getGlyph6; break; + case 12: ttf->mapper= getGlyph12; break; + default: +#if OSL_DEBUG_LEVEL > 1 + /*- if the cmap table is really broken */ + printf("%s: %d is not a recognized cmap format.\n", ttf->fname, GetUInt16(ttf->cmap, 0, 1)); +#endif + ttf->cmapType = CMAP_NOT_USABLE; + ttf->cmap = 0; + ttf->mapper = 0; + } + } +} + +static void GetKern(TrueTypeFont *ttf) +{ + sal_uInt8 *table = getTable(ttf, O_kern); + sal_uInt8 *ptr; + sal_uInt32 i; + /* + sal_uInt16 v1; + sal_uInt32 v2; + */ + + if (!table) goto badtable; + + if (GetUInt16(table, 0, 1) == 0) { /* Traditional Microsoft style table with USHORT version and nTables fields */ + ttf->nkern = GetUInt16(table, 2, 1); + ttf->kerntables = (sal_uInt8**)calloc(ttf->nkern, sizeof(sal_uInt8 *)); + assert(ttf->kerntables != 0); + memset(ttf->kerntables, 0, ttf->nkern * sizeof(sal_uInt8 *)); + ttf->kerntype = KT_MICROSOFT; + ptr = table + 4; + for (i=0; i < ttf->nkern; i++) { + ttf->kerntables[i] = ptr; + ptr += GetUInt16(ptr, 2, 1); + /* sanity check */ + if( ptr > ttf->ptr+ttf->fsize ) + { + free( ttf->kerntables ); + goto badtable; + } + } + return; + } + + if (GetUInt32(table, 0, 1) == 0x00010000) { /* MacOS style kern tables: fixed32 version and sal_uInt32 nTables fields */ + ttf->nkern = GetUInt32(table, 4, 1); + ttf->kerntables = (sal_uInt8**)calloc(ttf->nkern, sizeof(sal_uInt8*)); + assert(ttf->kerntables != 0); + memset(ttf->kerntables, 0, ttf->nkern * sizeof(sal_uInt8 *)); + ttf->kerntype = KT_APPLE_NEW; + ptr = table + 8; + for (i = 0; i < ttf->nkern; i++) { + ttf->kerntables[i] = ptr; + ptr += GetUInt32(ptr, 0, 1); + /* sanity check; there are some fonts that are broken in this regard */ + if( ptr > ttf->ptr+ttf->fsize ) + { + free( ttf->kerntables ); + goto badtable; + } + } + return; + } + + badtable: + ttf->kerntype = KT_NONE; + ttf->kerntables = 0; + + return; +} + +#ifdef TEST5 +/* KernGlyphsPrim?() functions expect the caller to ensure the validity of their arguments and + * that x and y elements of the kern array are initialized to zeroes + */ +static void KernGlyphsPrim1(TrueTypeFont *ttf, sal_uInt16 *glyphs, int nglyphs, int wmode, KernData *kern) +{ + (void)ttf; /* avoid warning */ + (void)glyphs; /* avoid warning */ + (void)nglyphs; /* avoid warning */ + (void)wmode; /* avoid warning */ + (void)nglyphs; /* avoid warning */ + (void)kern; /* avoid warning */ + fprintf(stderr, "MacOS kerning tables have not been implemented yet!\n"); +} + +static void KernGlyphsPrim2(TrueTypeFont *ttf, sal_uInt16 *glyphs, int nglyphs, int wmode, KernData *kern) +{ + sal_uInt32 i, j; + sal_uInt32 gpair; + + if( ! nglyphs ) + return; + + for (i = 0; i < (sal_uInt32)nglyphs - 1; i++) { + gpair = (glyphs[i] << 16) | glyphs[i+1]; +#ifdef DEBUG2 + /* All fonts with MS kern table that I've seen so far contain just one kern subtable. + * MS kern documentation is very poor and I doubt that font developers will be using + * several subtables. I expect them to be using OpenType tables instead. + * According to MS documention, format 2 subtables are not supported by Windows and OS/2. + */ + if (ttf->nkern > 1) { + fprintf(stderr, "KernGlyphsPrim2: %d kern tables found.\n", ttf->nkern); + } +#endif + for (j = 0; j < ttf->nkern; j++) { + sal_uInt16 coverage = GetUInt16(ttf->kerntables[j], 4, 1); + sal_uInt8 *ptr; + int npairs; + sal_uInt32 t; + int l, r, k; + + if (! ((coverage & 1) ^ wmode)) continue; + if ((coverage & 0xFFFE) != 0) { +#ifdef DEBUG2 + fprintf(stderr, "KernGlyphsPrim2: coverage flags are not supported: %04X.\n", coverage); +#endif + continue; + } + ptr = ttf->kerntables[j]; + npairs = GetUInt16(ptr, 6, 1); + ptr += 14; + l = 0; + r = npairs; + do { + k = (l + r) >> 1; + t = GetUInt32(ptr, k * 6, 1); + if (gpair >= t) l = k + 1; + if (gpair <= t) r = k - 1; + } while (l <= r); + if (l - r == 2) { + if (!wmode) { + kern[i].x = XUnits(ttf->unitsPerEm, GetInt16(ptr, 4 + (l-1) * 6, 1)); + } else { + kern[i].y = XUnits(ttf->unitsPerEm, GetInt16(ptr, 4 + (l-1) * 6, 1)); + } + /* !wmode ? kern[i].x : kern[i].y = GetInt16(ptr, 4 + (l-1) * 6, 1); */ + } + } + } +} +#endif + +/*- Public functions */ /*FOLD00*/ + +int CountTTCFonts(const char* fname) +{ + int nFonts = 0; + sal_uInt8 buffer[12]; + FILE* fd = fopen(fname, "rb"); + if( fd ) { + if (fread(buffer, 1, 12, fd) == 12) { + if(GetUInt32(buffer, 0, 1) == T_ttcf ) + nFonts = GetUInt32(buffer, 8, 1); + } + fclose(fd); + } + return nFonts; +} + +static void allocTrueTypeFont( TrueTypeFont** ttf ) +{ + *ttf = (TrueTypeFont*)calloc(1,sizeof(TrueTypeFont)); + if( *ttf != NULL ) + { + (*ttf)->tag = 0; + (*ttf)->fname = 0; + (*ttf)->fsize = -1; + (*ttf)->ptr = 0; + (*ttf)->nglyphs = 0xFFFFFFFF; + (*ttf)->pGSubstitution = 0; + } +} + +/* forward declariotn for the two entry points to use*/ +static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t ); + +#if !defined(WIN32) && !defined(OS2) +int OpenTTFontFile( const char* fname, sal_uInt32 facenum, TrueTypeFont** ttf ) +{ + int ret, fd = -1; + struct stat st; + + if (!fname || !*fname) return SF_BADFILE; + + allocTrueTypeFont( ttf ); + if( ! *ttf ) + return SF_MEMORY; + + (*ttf)->fname = strdup(fname); + if( ! (*ttf)->fname ) + { + ret = SF_MEMORY; + goto cleanup; + } + + fd = open(fname, O_RDONLY); + + if (fd == -1) { + ret = SF_BADFILE; + goto cleanup; + } + + if (fstat(fd, &st) == -1) { + ret = SF_FILEIO; + goto cleanup; + } + + (*ttf)->fsize = st.st_size; + + /* On Mac OS, most likely will happen if a Mac user renames a font file + * to be .ttf when its really a Mac resource-based font. + * Size will be 0, but fonts smaller than 4 bytes would be broken anyway. + */ + if ((*ttf)->fsize == 0) { + ret = SF_BADFILE; + goto cleanup; + } + + + if (((*ttf)->ptr = (sal_uInt8 *) mmap(0, (*ttf)->fsize, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { + ret = SF_MEMORY; + goto cleanup; + } + close(fd); + + return doOpenTTFont( facenum, *ttf ); + +cleanup: + if (fd != -1) close(fd); + /*- t and t->fname have been allocated! */ + free((*ttf)->fname); + free(*ttf); + *ttf = NULL; + return ret; +} +#endif + +int OpenTTFontBuffer(void* pBuffer, sal_uInt32 nLen, sal_uInt32 facenum, TrueTypeFont** ttf) +{ + allocTrueTypeFont( ttf ); + if( *ttf == NULL ) + return SF_MEMORY; + + (*ttf)->fname = NULL; + (*ttf)->fsize = nLen; + (*ttf)->ptr = (sal_uInt8*)pBuffer; + + return doOpenTTFont( facenum, *ttf ); +} + +static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t ) +{ + int i; + sal_uInt32 length, tag; + sal_uInt32 tdoffset = 0; /* offset to TableDirectory in a TTC file. For TTF files is 0 */ + int indexfmt, k; + + sal_uInt32 version = GetInt32(t->ptr, 0, 1); + + if ((version == 0x00010000) || (version == T_true)) { + tdoffset = 0; + } else if (version == T_ttcf) { /*- TrueType collection */ + if (GetUInt32(t->ptr, 4, 1) != 0x00010000) { + CloseTTFont(t); + return SF_TTFORMAT; + } + if (facenum >= GetUInt32(t->ptr, 8, 1)) { + CloseTTFont(t); + return SF_FONTNO; + } + tdoffset = GetUInt32(t->ptr, 12 + 4 * facenum, 1); + } else { + CloseTTFont(t); + return SF_TTFORMAT; + } + +#ifdef DEBUG2 + fprintf(stderr, "tdoffset: %d\n", tdoffset); +#endif + + /* magic number */ + t->tag = TTFontClassTag; + + t->ntables = GetUInt16(t->ptr + tdoffset, 4, 1); + if( t->ntables >= 128 ) + return SF_TTFORMAT; + + t->tables = (sal_uInt8**)calloc(NUM_TAGS, sizeof(sal_uInt8*)); + assert(t->tables != 0); + t->tlens = (sal_uInt32*)calloc(NUM_TAGS, sizeof(sal_uInt32)); + assert(t->tlens != 0); + + memset(t->tables, 0, NUM_TAGS * sizeof(void *)); + memset(t->tlens, 0, NUM_TAGS * sizeof(sal_uInt32)); + + /* parse the tables */ + for (i=0; i<(int)t->ntables; i++) { + int nIndex; + tag = GetUInt32(t->ptr + tdoffset + 12, 16 * i, 1); + switch( tag ) { + case T_maxp: nIndex = O_maxp; break; + case T_glyf: nIndex = O_glyf; break; + case T_head: nIndex = O_head; break; + case T_loca: nIndex = O_loca; break; + case T_name: nIndex = O_name; break; + case T_hhea: nIndex = O_hhea; break; + case T_hmtx: nIndex = O_hmtx; break; + case T_cmap: nIndex = O_cmap; break; + case T_vhea: nIndex = O_vhea; break; + case T_vmtx: nIndex = O_vmtx; break; + case T_OS2 : nIndex = O_OS2; break; + case T_post: nIndex = O_post; break; + case T_kern: nIndex = O_kern; break; + case T_cvt : nIndex = O_cvt; break; + case T_prep: nIndex = O_prep; break; + case T_fpgm: nIndex = O_fpgm; break; + case T_gsub: nIndex = O_gsub; break; + default: nIndex = -1; break; + } + if( nIndex >= 0 ) { + sal_uInt32 nTableOffset = GetUInt32(t->ptr + tdoffset + 12, 16 * i + 8, 1); + length = GetUInt32(t->ptr + tdoffset + 12, 16 * i + 12, 1); + t->tables[nIndex] = t->ptr + nTableOffset; + t->tlens[nIndex] = length; + } + } + + /* Fixup offsets when only a TTC extract was provided */ + if( facenum == (sal_uInt32)~0 ) { + sal_uInt8* pHead = (sal_uInt8*)t->tables[O_head]; + if( !pHead ) + return SF_TTFORMAT; + /* limit Head candidate to TTC extract's limits */ + if( pHead > t->ptr + (t->fsize - 54) ) + pHead = t->ptr + (t->fsize - 54); + /* TODO: find better method than searching head table's magic */ + sal_uInt8* p = NULL; + for( p = pHead + 12; p > t->ptr; --p ) { + if( p[0]==0x5F && p[1]==0x0F && p[2]==0x3C && p[3]==0xF5 ) { + int nDelta = (pHead + 12) - p, j; + if( nDelta ) + for( j=0; j<NUM_TAGS; ++j ) + if( t->tables[j] ) + *(char**)&t->tables[j] -= nDelta; + break; + } + } + if( p <= t->ptr ) + return SF_TTFORMAT; + } + + /* Check the table offsets after TTC correction */ + for (i=0; i<NUM_TAGS; i++) { + /* sanity check: table must lay completely within the file + * at this point one could check the checksum of all contained + * tables, but this would be quite time intensive. + * Try to fix tables, so we can cope with minor problems. + */ + + if( (sal_uInt8*)t->tables[i] < t->ptr ) + { + t->tlens[i] = 0; + t->tables[i] = NULL; +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "font file %s has bad table offset (tagnum=%d)\n", t->fname, i ); +#endif + } + else if( (sal_uInt8*)t->tables[i] + t->tlens[i] > t->ptr + t->fsize ) + { + int nMaxLen = (t->ptr + t->fsize) - (sal_uInt8*)t->tables[i]; + if( nMaxLen < 0 ) + nMaxLen = 0; + t->tlens[i] = nMaxLen; +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "font file %s has too big table (tagnum=%d)\n", t->fname, i ); +#endif + } + } + + /* At this point TrueTypeFont is constructed, now need to verify the font format + and read the basic font properties */ + + /* The following tables are absolutely required: + * maxp, head, glyf, loca, name, cmap + */ + + if (!(getTable(t, O_maxp) && getTable(t, O_head) && getTable(t, O_glyf) && getTable(t, O_loca) && getTable(t, O_name) && getTable(t, O_cmap) )) { + CloseTTFont(t); + return SF_TTFORMAT; + } + + sal_uInt8* table = getTable(t, O_maxp); + t->nglyphs = GetUInt16(table, 4, 1); + + table = getTable(t, O_head); + t->unitsPerEm = GetUInt16(table, 18, 1); + indexfmt = GetInt16(table, 50, 1); + + if( ((indexfmt != 0) && (indexfmt != 1)) || (t->unitsPerEm <= 0) ) { + CloseTTFont(t); + return SF_TTFORMAT; + } + + k = (getTableSize(t, O_loca) / (indexfmt ? 4 : 2)) - 1; + if (k < (int)t->nglyphs) t->nglyphs = k; /* Hack for broken Chinese fonts */ + + table = getTable(t, O_loca); + + t->goffsets = (sal_uInt32 *) calloc(1+t->nglyphs, sizeof(sal_uInt32)); + assert(t->goffsets != 0); + + for (i = 0; i <= (int)t->nglyphs; i++) { + t->goffsets[i] = indexfmt ? GetUInt32(table, i << 2, 1) : (sal_uInt32)GetUInt16(table, i << 1, 1) << 1; + } + + table = getTable(t, O_hhea); + t->numberOfHMetrics = (table != 0) ? GetUInt16(table, 34, 1) : 0; + + table = getTable(t, O_vhea); + t->numOfLongVerMetrics = (table != 0) ? GetUInt16(table, 34, 1) : 0; + + GetNames(t); + FindCmap(t); + GetKern(t); + ReadGSUB( t, 0, 0 ); + + return SF_OK; +} + +void CloseTTFont(TrueTypeFont *ttf) /*FOLD01*/ +{ + if (ttf->tag != TTFontClassTag) return; + +#if !defined(WIN32) && !defined(OS2) + if( ttf->fname ) + munmap((char *) ttf->ptr, ttf->fsize); +#endif + free(ttf->fname); + free(ttf->goffsets); + free(ttf->psname); + free(ttf->family); + if( ttf->ufamily ) + free( ttf->ufamily ); + free(ttf->subfamily); + if( ttf->usubfamily ) + free( ttf->usubfamily ); + free(ttf->tables); + free(ttf->tlens); + free(ttf->kerntables); + + ReleaseGSUB(ttf); + + free(ttf); + return; +} + +int GetTTGlyphPoints(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray) +{ + return GetTTGlyphOutline(ttf, glyphID, pointArray, 0, 0); +} + +int GetTTGlyphComponents(TrueTypeFont *ttf, sal_uInt32 glyphID, std::vector< sal_uInt32 >& glyphlist) +{ + sal_uInt8 *ptr, *glyf = getTable(ttf, O_glyf); + int n = 1; + + if (glyphID >= ttf->nglyphs) return 0; + ptr = glyf + ttf->goffsets[glyphID]; + + glyphlist.push_back( glyphID ); + + if (GetInt16(ptr, 0, 1) == -1) { + sal_uInt16 flags, index; + ptr += 10; + do { + flags = GetUInt16(ptr, 0, 1); + index = GetUInt16(ptr, 2, 1); + + ptr += 4; + n += GetTTGlyphComponents(ttf, index, glyphlist); + + if (flags & ARG_1_AND_2_ARE_WORDS) { + ptr += 4; + } else { + ptr += 2; + } + + if (flags & WE_HAVE_A_SCALE) { + ptr += 2; + } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) { + ptr += 4; + } else if (flags & WE_HAVE_A_TWO_BY_TWO) { + ptr += 8; + } + } while (flags & MORE_COMPONENTS); + } + + return n; +} + +#ifndef NO_TYPE3 +int CreateT3FromTTGlyphs(TrueTypeFont *ttf, FILE *outf, const char *fname, /*FOLD00*/ + sal_uInt16 *glyphArray, sal_uInt8 *encoding, int nGlyphs, + int wmode) +{ + ControlPoint *pa; + PSPathElement *path; + int i, j, r, n; + sal_uInt8 *table = getTable(ttf, O_head); + TTGlyphMetrics metrics; + int UPEm = ttf->unitsPerEm; + + const char *h01 = "%%!PS-AdobeFont-%d.%d-%d.%d\n"; + const char *h02 = "%% Creator: %s %s %s\n"; + const char *h09 = "%% Original font name: %s\n"; + + const char *h10 = + "30 dict begin\n" + "/PaintType 0 def\n" + "/FontType 3 def\n" + "/StrokeWidth 0 def\n"; + + const char *h11 = "/FontName (%s) cvn def\n"; + + /* + const char *h12 = "%/UniqueID %d def\n"; + */ + const char *h13 = "/FontMatrix [.001 0 0 .001 0 0] def\n"; + const char *h14 = "/FontBBox [%d %d %d %d] def\n"; + + const char *h15= + "/Encoding 256 array def\n" + " 0 1 255 {Encoding exch /.notdef put} for\n"; + + const char *h16 = " Encoding %d /glyph%d put\n"; + const char *h17 = "/XUID [103 0 0 16#%08X %d 16#%08X 16#%08X] def\n"; + + const char *h30 = "/CharProcs %d dict def\n"; + const char *h31 = " CharProcs begin\n"; + const char *h32 = " /.notdef {} def\n"; + const char *h33 = " /glyph%d {\n"; + const char *h34 = " } bind def\n"; + const char *h35 = " end\n"; + + const char *h40 = + "/BuildGlyph {\n" + " exch /CharProcs get exch\n" + " 2 copy known not\n" + " {pop /.notdef} if\n" + " get exec\n" + "} bind def\n" + "/BuildChar {\n" + " 1 index /Encoding get exch get\n" + " 1 index /BuildGlyph get exec\n" + "} bind def\n" + "currentdict end\n"; + + const char *h41 = "(%s) cvn exch definefont pop\n"; + + + if (!((nGlyphs > 0) && (nGlyphs <= 256))) return SF_GLYPHNUM; + if (!glyphArray) return SF_BADARG; + if (!fname) fname = ttf->psname; + + fprintf(outf, h01, GetInt16(table, 0, 1), GetUInt16(table, 2, 1), GetInt16(table, 4, 1), GetUInt16(table, 6, 1)); + fprintf(outf, h02, modname, modver, modextra); + fprintf(outf, h09, ttf->psname); + + fprintf(outf, h10); + fprintf(outf, h11, fname); +/* fprintf(outf, h12, 4000000); */ + + /* XUID generation: + * 103 0 0 C1 C2 C3 C4 + * C1 - CRC-32 of the entire source TrueType font + * C2 - number of glyphs in the subset + * C3 - CRC-32 of the glyph array + * C4 - CRC-32 of the encoding array + * + * All CRC-32 numbers are presented as hexadecimal numbers + */ + + fprintf(outf, h17, rtl_crc32(0, ttf->ptr, ttf->fsize), nGlyphs, rtl_crc32(0, glyphArray, nGlyphs * 2), rtl_crc32(0, encoding, nGlyphs)); + fprintf(outf, h13); + fprintf(outf, h14, XUnits(UPEm, GetInt16(table, 36, 1)), XUnits(UPEm, GetInt16(table, 38, 1)), XUnits(UPEm, GetInt16(table, 40, 1)), XUnits(UPEm, GetInt16(table, 42, 1))); + fprintf(outf, h15); + + for (i = 0; i < nGlyphs; i++) { + fprintf(outf, h16, encoding[i], i); + } + + fprintf(outf, h30, nGlyphs+1); + fprintf(outf, h31); + fprintf(outf, h32); + + for (i = 0; i < nGlyphs; i++) { + fprintf(outf, h33, i); + r = GetTTGlyphOutline(ttf, glyphArray[i] < ttf->nglyphs ? glyphArray[i] : 0, &pa, &metrics, 0); + + if (r > 0) { + n = BSplineToPSPath(pa, r, &path); + } else { + n = 0; /* glyph might have zero contours but valid metrics ??? */ + path = 0; + if (r < 0) { /* glyph is not present in the font - pa array was not allocated, so no need to free it */ + continue; + } + } + fprintf(outf, "\t%d %d %d %d %d %d setcachedevice\n", + wmode == 0 ? XUnits(UPEm, metrics.aw) : 0, + wmode == 0 ? 0 : -XUnits(UPEm, metrics.ah), + XUnits(UPEm, metrics.xMin), + XUnits(UPEm, metrics.yMin), + XUnits(UPEm, metrics.xMax), + XUnits(UPEm, metrics.yMax)); + + for (j = 0; j < n; j++) + { + switch (path[j].type) + { + case PS_MOVETO: + fprintf(outf, "\t%d %d moveto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1)); + break; + + case PS_LINETO: + fprintf(outf, "\t%d %d lineto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1)); + break; + + case PS_CURVETO: + fprintf(outf, "\t%d %d %d %d %d %d curveto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1), XUnits(UPEm, path[j].x2), XUnits(UPEm, path[j].y2), XUnits(UPEm, path[j].x3), XUnits(UPEm, path[j].y3)); + break; + + case PS_CLOSEPATH: + fprintf(outf, "\tclosepath\n"); + break; + case PS_NOOP: + break; + } + } + if (n > 0) fprintf(outf, "\tfill\n"); /* if glyph is not a whitespace character */ + + fprintf(outf, h34); + + free(pa); + free(path); + } + fprintf(outf, h35); + + fprintf(outf, h40); + fprintf(outf, h41, fname); + + return SF_OK; +} +#endif + +#ifndef NO_TTCR +int CreateTTFromTTGlyphs(TrueTypeFont *ttf, + const char *fname, + sal_uInt16 *glyphArray, + sal_uInt8 *encoding, + int nGlyphs, + int nNameRecs, + NameRecord *nr, + sal_uInt32 flags) +{ + TrueTypeCreator *ttcr; + TrueTypeTable *head=0, *hhea=0, *maxp=0, *cvt=0, *prep=0, *glyf=0, *fpgm=0, *cmap=0, *name=0, *post = 0, *os2 = 0; + sal_uInt8 *p; + int i; + int res; + + TrueTypeCreatorNewEmpty(T_true, &ttcr); + + /** name **/ + + if (flags & TTCF_AutoName) { + /* not implemented yet + NameRecord *names; + NameRecord newname; + int n = GetTTNameRecords(ttf, &names); + int n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0, n6 = 0; + sal_uInt8 *cp1; + sal_uInt8 suffix[32]; + sal_uInt32 c1 = crc32(glyphArray, nGlyphs * 2); + sal_uInt32 c2 = crc32(encoding, nGlyphs); + int len; + snprintf(suffix, 31, "S%08X%08X-%d", c1, c2, nGlyphs); + + name = TrueTypeTableNew_name(0, 0); + for (i = 0; i < n; i++) { + if (names[i].platformID == 1 && names[i].encodingID == 0 && names[i].languageID == 0 && names[i].nameID == 1) { + + memcpy(newname, names+i, sizeof(NameRecord)); + newname.slen = name[i].slen + strlen(suffix); + */ + const sal_uInt8 ptr[] = {0,'T',0,'r',0,'u',0,'e',0,'T',0,'y',0,'p',0,'e',0,'S',0,'u',0,'b',0,'s',0,'e',0,'t'}; + NameRecord n1 = {1, 0, 0, 6, 14, (sal_uInt8*)"TrueTypeSubset"}; + NameRecord n2 = {3, 1, 1033, 6, 28, 0}; + n2.sptr = (sal_uInt8 *) ptr; + name = TrueTypeTableNew_name(0, 0); + nameAdd(name, &n1); + nameAdd(name, &n2); + } else { + if (nNameRecs == 0) { + NameRecord *names; + int n = GetTTNameRecords(ttf, &names); + name = TrueTypeTableNew_name(n, names); + DisposeNameRecords(names, n); + } else { + name = TrueTypeTableNew_name(nNameRecs, nr); + } + } + + /** maxp **/ + maxp = TrueTypeTableNew_maxp(getTable(ttf, O_maxp), getTableSize(ttf, O_maxp)); + + /** hhea **/ + p = getTable(ttf, O_hhea); + if (p) { + hhea = TrueTypeTableNew_hhea(GetUInt16(p, 4, 1), GetUInt16(p, 6, 1), GetUInt16(p, 8, 1), GetUInt16(p, 18, 1), GetUInt16(p, 20, 1)); + } else { + hhea = TrueTypeTableNew_hhea(0, 0, 0, 0, 0); + } + + /** head **/ + + p = getTable(ttf, O_head); + assert(p != 0); + head = TrueTypeTableNew_head(GetUInt32(p, 4, 1), + GetUInt16(p, 16, 1), + GetUInt16(p, 18, 1), + p+20, + GetUInt16(p, 44, 1), + GetUInt16(p, 46, 1), + GetInt16(p, 48, 1)); + + + /** glyf **/ + + glyf = TrueTypeTableNew_glyf(); + sal_uInt32* gID = (sal_uInt32*)scalloc(nGlyphs, sizeof(sal_uInt32)); + + for (i = 0; i < nGlyphs; i++) { + gID[i] = glyfAdd(glyf, GetTTRawGlyphData(ttf, glyphArray[i]), ttf); + } + + /** cmap **/ + cmap = TrueTypeTableNew_cmap(); + + for (i=0; i < nGlyphs; i++) { + cmapAdd(cmap, 0x010000, encoding[i], gID[i]); + } + + /** cvt **/ + if ((p = getTable(ttf, O_cvt)) != 0) { + cvt = TrueTypeTableNew(T_cvt, getTableSize(ttf, O_cvt), p); + } + + /** prep **/ + if ((p = getTable(ttf, O_prep)) != 0) { + prep = TrueTypeTableNew(T_prep, getTableSize(ttf, O_prep), p); + } + + /** fpgm **/ + if ((p = getTable(ttf, O_fpgm)) != 0) { + fpgm = TrueTypeTableNew(T_fpgm, getTableSize(ttf, O_fpgm), p); + } + + /** post **/ + if ((p = getTable(ttf, O_post)) != 0) { + post = TrueTypeTableNew_post(0x00030000, + GetUInt32(p, 4, 1), + GetUInt16(p, 8, 1), + GetUInt16(p, 10, 1), + GetUInt16(p, 12, 1)); + } else { + post = TrueTypeTableNew_post(0x00030000, 0, 0, 0, 0); + } + + if (flags & TTCF_IncludeOS2) { + if ((p = getTable(ttf, O_OS2)) != 0) { + os2 = TrueTypeTableNew(T_OS2, getTableSize(ttf, O_OS2), p); + } + } + + AddTable(ttcr, name); AddTable(ttcr, maxp); AddTable(ttcr, hhea); + AddTable(ttcr, head); AddTable(ttcr, glyf); AddTable(ttcr, cmap); + AddTable(ttcr, cvt ); AddTable(ttcr, prep); AddTable(ttcr, fpgm); + AddTable(ttcr, post); AddTable(ttcr, os2); + + if ((res = StreamToFile(ttcr, fname)) != SF_OK) { +#if OSL_DEBUG_LEVEL > 1 + fprintf(stderr, "StreamToFile: error code: %d.\n", res); +#endif + } + + TrueTypeCreatorDispose(ttcr); + free(gID); + + return res; +} +#endif + + +#ifndef NO_TYPE42 +static GlyphOffsets *GlyphOffsetsNew(sal_uInt8 *sfntP) +{ + GlyphOffsets* res = (GlyphOffsets*)smalloc(sizeof(GlyphOffsets)); + sal_uInt8 *loca = NULL; + sal_uInt16 i, numTables = GetUInt16(sfntP, 4, 1); + sal_uInt32 locaLen = 0; + sal_Int16 indexToLocFormat = 0; + + for (i = 0; i < numTables; i++) { + sal_uInt32 tag = GetUInt32(sfntP + 12, 16 * i, 1); + sal_uInt32 off = GetUInt32(sfntP + 12, 16 * i + 8, 1); + sal_uInt32 len = GetUInt32(sfntP + 12, 16 * i + 12, 1); + + if (tag == T_loca) { + loca = sfntP + off; + locaLen = len; + } else if (tag == T_head) { + indexToLocFormat = GetInt16(sfntP + off, 50, 1); + } + } + + res->nGlyphs = locaLen / ((indexToLocFormat == 1) ? 4 : 2); + assert(res->nGlyphs != 0); + res->offs = (sal_uInt32*)scalloc(res->nGlyphs, sizeof(sal_uInt32)); + + for (i = 0; i < res->nGlyphs; i++) { + if (indexToLocFormat == 1) { + res->offs[i] = GetUInt32(loca, i * 4, 1); + } else { + res->offs[i] = GetUInt16(loca, i * 2, 1) << 1; + } + } + return res; +} + +static void GlyphOffsetsDispose(GlyphOffsets *_this) +{ + if (_this) { + free(_this->offs); + free(_this); + } +} + +static void DumpSfnts(FILE *outf, sal_uInt8 *sfntP) +{ + HexFmt *h = HexFmtNew(outf); + sal_uInt16 i, numTables = GetUInt16(sfntP, 4, 1); + GlyphOffsets *go = GlyphOffsetsNew(sfntP); + sal_uInt8 pad[] = {0,0,0,0}; /* zeroes */ + + assert(numTables <= 9); /* Type42 has 9 required tables */ + + sal_uInt32* offs = (sal_uInt32*)scalloc(numTables, sizeof(sal_uInt32)); +// sal_uInt32* lens = (sal_uInt32*)scalloc(numTables, sizeof(sal_uInt32)); + + fputs("/sfnts [", outf); + HexFmtOpenString(h); + HexFmtBlockWrite(h, sfntP, 12); /* stream out the Offset Table */ + HexFmtBlockWrite(h, sfntP+12, 16 * numTables); /* stream out the Table Directory */ + + for (i=0; i<numTables; i++) { + sal_uInt32 tag = GetUInt32(sfntP + 12, 16 * i, 1); + sal_uInt32 off = GetUInt32(sfntP + 12, 16 * i + 8, 1); + sal_uInt32 len = GetUInt32(sfntP + 12, 16 * i + 12, 1); + + if (tag != T_glyf) { + HexFmtBlockWrite(h, sfntP + off, len); + } else { + sal_uInt8 *glyf = sfntP + off; + sal_uInt32 o, l, j; + for (j = 0; j < go->nGlyphs - 1; j++) { + o = go->offs[j]; + l = go->offs[j + 1] - o; + HexFmtBlockWrite(h, glyf + o, l); + } + } + HexFmtBlockWrite(h, pad, (4 - (len & 3)) & 3); + } + HexFmtCloseString(h); + fputs("] def\n", outf); + GlyphOffsetsDispose(go); + HexFmtDispose(h); + free(offs); +// free(lens); +} + +int CreateT42FromTTGlyphs(TrueTypeFont *ttf, + FILE *outf, + const char *psname, + sal_uInt16 *glyphArray, + sal_uInt8 *encoding, + int nGlyphs) +{ + TrueTypeCreator *ttcr; + TrueTypeTable *head=0, *hhea=0, *maxp=0, *cvt=0, *prep=0, *glyf=0, *fpgm=0; + sal_uInt8 *p; + int i; + int res; + + sal_uInt32 ver, rev; + sal_uInt8 *headP; + + sal_uInt8 *sfntP; + sal_uInt32 sfntLen; + int UPEm = ttf->unitsPerEm; + + if (nGlyphs >= 256) return SF_GLYPHNUM; + + assert(psname != 0); + + TrueTypeCreatorNewEmpty(T_true, &ttcr); + + /* head */ + headP = p = getTable(ttf, O_head); + assert(p != 0); + head = TrueTypeTableNew_head(GetUInt32(p, 4, 1), GetUInt16(p, 16, 1), GetUInt16(p, 18, 1), p+20, GetUInt16(p, 44, 1), GetUInt16(p, 46, 1), GetInt16(p, 48, 1)); + ver = GetUInt32(p, 0, 1); + rev = GetUInt32(p, 4, 1); + + /** hhea **/ + p = getTable(ttf, O_hhea); + if (p) { + hhea = TrueTypeTableNew_hhea(GetUInt16(p, 4, 1), GetUInt16(p, 6, 1), GetUInt16(p, 8, 1), GetUInt16(p, 18, 1), GetUInt16(p, 20, 1)); + } else { + hhea = TrueTypeTableNew_hhea(0, 0, 0, 0, 0); + } + + /** maxp **/ + maxp = TrueTypeTableNew_maxp(getTable(ttf, O_maxp), getTableSize(ttf, O_maxp)); + + /** cvt **/ + if ((p = getTable(ttf, O_cvt)) != 0) { + cvt = TrueTypeTableNew(T_cvt, getTableSize(ttf, O_cvt), p); + } + + /** prep **/ + if ((p = getTable(ttf, O_prep)) != 0) { + prep = TrueTypeTableNew(T_prep, getTableSize(ttf, O_prep), p); + } + + /** fpgm **/ + if ((p = getTable(ttf, O_fpgm)) != 0) { + fpgm = TrueTypeTableNew(T_fpgm, getTableSize(ttf, O_fpgm), p); + } + + /** glyf **/ + glyf = TrueTypeTableNew_glyf(); + sal_uInt16* gID = (sal_uInt16*)scalloc(nGlyphs, sizeof(sal_uInt32)); + + for (i = 0; i < nGlyphs; i++) { + gID[i] = (sal_uInt16)glyfAdd(glyf, GetTTRawGlyphData(ttf, glyphArray[i]), ttf); + } + + AddTable(ttcr, head); AddTable(ttcr, hhea); AddTable(ttcr, maxp); AddTable(ttcr, cvt); + AddTable(ttcr, prep); AddTable(ttcr, glyf); AddTable(ttcr, fpgm); + + if ((res = StreamToMemory(ttcr, &sfntP, &sfntLen)) != SF_OK) { + TrueTypeCreatorDispose(ttcr); + free(gID); + return res; + } + + fprintf(outf, "%%!PS-TrueTypeFont-%d.%d-%d.%d\n", (int)(ver>>16), (int)(ver & 0xFFFF), (int)(rev>>16), (int)(rev & 0xFFFF)); + fprintf(outf, "%%%%Creator: %s %s %s\n", modname, modver, modextra); + fprintf(outf, "%%- Font subset generated from a source font file: '%s'\n", ttf->fname); + fprintf(outf, "%%- Original font name: %s\n", ttf->psname); + fprintf(outf, "%%- Original font family: %s\n", ttf->family); + fprintf(outf, "%%- Original font sub-family: %s\n", ttf->subfamily); + fprintf(outf, "11 dict begin\n"); + fprintf(outf, "/FontName (%s) cvn def\n", psname); + fprintf(outf, "/PaintType 0 def\n"); + fprintf(outf, "/FontMatrix [1 0 0 1 0 0] def\n"); + fprintf(outf, "/FontBBox [%d %d %d %d] def\n", XUnits(UPEm, GetInt16(headP, 36, 1)), XUnits(UPEm, GetInt16(headP, 38, 1)), XUnits(UPEm, GetInt16(headP, 40, 1)), XUnits(UPEm, GetInt16(headP, 42, 1))); + fprintf(outf, "/FontType 42 def\n"); + fprintf(outf, "/Encoding 256 array def\n"); + fprintf(outf, " 0 1 255 {Encoding exch /.notdef put} for\n"); + + for (i = 1; i<nGlyphs; i++) { + fprintf(outf, "Encoding %d /glyph%d put\n", encoding[i], gID[i]); + } + fprintf(outf, "/XUID [103 0 1 16#%08X %d 16#%08X 16#%08X] def\n", (unsigned int)rtl_crc32(0, ttf->ptr, ttf->fsize), (unsigned int)nGlyphs, (unsigned int)rtl_crc32(0, glyphArray, nGlyphs * 2), (unsigned int)rtl_crc32(0, encoding, nGlyphs)); + + DumpSfnts(outf, sfntP); + + /* dump charstrings */ + fprintf(outf, "/CharStrings %d dict dup begin\n", nGlyphs); + fprintf(outf, "/.notdef 0 def\n"); + for (i = 1; i < (int)glyfCount(glyf); i++) { + fprintf(outf,"/glyph%d %d def\n", i, i); + } + fprintf(outf, "end readonly def\n"); + + fprintf(outf, "FontName currentdict end definefont pop\n"); + TrueTypeCreatorDispose(ttcr); + free(gID); + free(sfntP); + return SF_OK; +} +#endif + + +#ifndef NO_MAPPERS +int MapString(TrueTypeFont *ttf, sal_uInt16 *str, int nchars, sal_uInt16 *glyphArray, int bvertical) +{ + int i; + sal_uInt16 *cp; + + if (ttf->cmapType == CMAP_NOT_USABLE ) return -1; + if (!nchars) return 0; + + if (glyphArray == 0) { + cp = str; + } else { + cp = glyphArray; + } + + switch (ttf->cmapType) { + case CMAP_MS_Symbol: + if( ttf->mapper == getGlyph0 ) { + sal_uInt16 aChar; + for( i = 0; i < nchars; i++ ) { + aChar = str[i]; + if( ( aChar & 0xf000 ) == 0xf000 ) + aChar &= 0x00ff; + cp[i] = aChar; + } + } + else if( glyphArray ) + memcpy(glyphArray, str, nchars * 2); + break; + + case CMAP_MS_Unicode: + if (glyphArray != 0) { + memcpy(glyphArray, str, nchars * 2); + } + break; + + case CMAP_MS_ShiftJIS: TranslateString12(str, cp, nchars); break; + case CMAP_MS_Big5: TranslateString13(str, cp, nchars); break; + case CMAP_MS_PRC: TranslateString14(str, cp, nchars); break; + case CMAP_MS_Wansung: TranslateString15(str, cp, nchars); break; + case CMAP_MS_Johab: TranslateString16(str, cp, nchars); break; + } + + for (i = 0; i < nchars; i++) { + cp[i] = (sal_uInt16)ttf->mapper(ttf->cmap, cp[i]); + if (cp[i]!=0 && bvertical!=0) + cp[i] = (sal_uInt16)UseGSUB(ttf,cp[i],bvertical); + } + return nchars; +} + +sal_uInt16 MapChar(TrueTypeFont *ttf, sal_uInt16 ch, int bvertical) +{ + switch (ttf->cmapType) { + case CMAP_MS_Symbol: + + if( ttf->mapper == getGlyph0 && ( ch & 0xf000 ) == 0xf000 ) + ch &= 0x00ff; + return (sal_uInt16)ttf->mapper(ttf->cmap, ch ); + + case CMAP_MS_Unicode: break; + case CMAP_MS_ShiftJIS: ch = TranslateChar12(ch); break; + case CMAP_MS_Big5: ch = TranslateChar13(ch); break; + case CMAP_MS_PRC: ch = TranslateChar14(ch); break; + case CMAP_MS_Wansung: ch = TranslateChar15(ch); break; + case CMAP_MS_Johab: ch = TranslateChar16(ch); break; + default: return 0; + } + ch = (sal_uInt16)ttf->mapper(ttf->cmap, ch); + if (ch!=0 && bvertical!=0) + ch = (sal_uInt16)UseGSUB(ttf,ch,bvertical); + return ch; +} + +int DoesVerticalSubstitution( TrueTypeFont *ttf, int bvertical) +{ + int nRet = 0; + if( bvertical) + nRet = HasVerticalGSUB( ttf); + return nRet; +} + +#endif + +int GetTTGlyphCount( TrueTypeFont* ttf ) +{ + return ttf->nglyphs; +} + +TTSimpleGlyphMetrics *GetTTSimpleGlyphMetrics(TrueTypeFont *ttf, sal_uInt16 *glyphArray, int nGlyphs, int mode) +{ + sal_uInt8* pTable; + int i; + sal_uInt16 glyphID; + sal_uInt32 n; + int UPEm = ttf->unitsPerEm; + int nTableSize; + + if (mode == 0) { + n = ttf->numberOfHMetrics; + pTable = getTable( ttf, O_hmtx ); + nTableSize = getTableSize( ttf, O_hmtx ); + } else { + n = ttf->numOfLongVerMetrics; + pTable = getTable( ttf, O_vmtx ); + nTableSize = getTableSize( ttf, O_vmtx ); + } + + if (!nGlyphs || !glyphArray) return 0; /* invalid parameters */ + if (!n || !pTable) return 0; /* the font does not contain the requested metrics */ + + TTSimpleGlyphMetrics* res = (TTSimpleGlyphMetrics*)calloc(nGlyphs, sizeof(TTSimpleGlyphMetrics)); + assert(res != 0); + + for (i=0; i<nGlyphs; i++) { + int nAdvOffset, nLsbOffset; + glyphID = glyphArray[i]; + + if (glyphID < n) { + nAdvOffset = 4 * glyphID; + nLsbOffset = nAdvOffset + 2; + } else { + nAdvOffset = 4 * (n - 1); + if( glyphID < ttf->nglyphs ) + nLsbOffset = 4 * n + 2 * (glyphID - n); + else /* font is broken -> use lsb of last hmetrics */ + nLsbOffset = nAdvOffset + 2; + } + + if( nAdvOffset >= nTableSize) + res[i].adv = 0; /* better than a crash for buggy fonts */ + else + res[i].adv = static_cast<sal_uInt16>( + XUnits( UPEm, GetUInt16( pTable, nAdvOffset, 1) ) ); + + if( nLsbOffset >= nTableSize) + res[i].sb = 0; /* better than a crash for buggy fonts */ + else + res[i].sb = static_cast<sal_Int16>( + XUnits( UPEm, GetInt16( pTable, nLsbOffset, 1) ) ); + } + + return res; +} + +#ifndef NO_MAPPERS +TTSimpleGlyphMetrics *GetTTSimpleCharMetrics(TrueTypeFont * ttf, sal_uInt16 firstChar, int nChars, int mode) +{ + TTSimpleGlyphMetrics *res = 0; + int i, n; + + sal_uInt16* str = (sal_uInt16*)malloc(nChars * 2); + assert(str != 0); + + for (i=0; i<nChars; i++) str[i] = (sal_uInt16)(firstChar + i); + if ((n = MapString(ttf, str, nChars, 0, mode)) != -1) { + res = GetTTSimpleGlyphMetrics(ttf, str, n, mode); + } + + free(str); + + return res; +} +#endif + +void GetTTGlobalFontInfo(TrueTypeFont *ttf, TTGlobalFontInfo *info) +{ + sal_uInt8 *table; + int UPEm = ttf->unitsPerEm; + + memset(info, 0, sizeof(TTGlobalFontInfo)); + + info->family = ttf->family; + info->ufamily = ttf->ufamily; + info->subfamily = ttf->subfamily; + info->usubfamily = ttf->usubfamily; + info->psname = ttf->psname; + info->symbolEncoded = (ttf->cmapType == CMAP_MS_Symbol); + + table = getTable(ttf, O_OS2); + if (table) { + info->weight = GetUInt16(table, 4, 1); + info->width = GetUInt16(table, 6, 1); + + /* There are 3 different versions of OS/2 table: original (68 bytes long), + * Microsoft old (78 bytes long) and Microsoft new (86 bytes long,) + * Apple's documentation recommends looking at the table length. + */ + if (getTableSize(ttf, O_OS2) > 68) { + info->typoAscender = XUnits(UPEm,GetInt16(table, 68, 1)); + info->typoDescender = XUnits(UPEm, GetInt16(table, 70, 1)); + info->typoLineGap = XUnits(UPEm, GetInt16(table, 72, 1)); + info->winAscent = XUnits(UPEm, GetUInt16(table, 74, 1)); + info->winDescent = XUnits(UPEm, GetUInt16(table, 76, 1)); + /* sanity check; some fonts treat winDescent as signed + * violating the standard */ + if( info->winDescent > 5*UPEm ) + info->winDescent = XUnits(UPEm, GetInt16(table, 76,1)); + } + if (ttf->cmapType == CMAP_MS_Unicode) { + info->rangeFlag = 1; + info->ur1 = GetUInt32(table, 42, 1); + info->ur2 = GetUInt32(table, 46, 1); + info->ur3 = GetUInt32(table, 50, 1); + info->ur4 = GetUInt32(table, 54, 1); + } + memcpy(info->panose, table + 32, 10); + info->typeFlags = GetUInt16( table, 8, 1 ); + } + + table = getTable(ttf, O_post); + if (table) { + info->pitch = GetUInt32(table, 12, 1); + info->italicAngle = GetInt32(table, 4, 1); + } + + table = getTable(ttf, O_head); /* 'head' tables is always there */ + info->xMin = XUnits(UPEm, GetInt16(table, 36, 1)); + info->yMin = XUnits(UPEm, GetInt16(table, 38, 1)); + info->xMax = XUnits(UPEm, GetInt16(table, 40, 1)); + info->yMax = XUnits(UPEm, GetInt16(table, 42, 1)); + info->macStyle = GetInt16(table, 44, 1); + + table = getTable(ttf, O_hhea); + if (table) { + info->ascender = XUnits(UPEm, GetInt16(table, 4, 1)); + info->descender = XUnits(UPEm, GetInt16(table, 6, 1)); + info->linegap = XUnits(UPEm, GetInt16(table, 8, 1)); + } + + table = getTable(ttf, O_vhea); + if (table) { + info->vascent = XUnits(UPEm, GetInt16(table, 4, 1)); + info->vdescent = XUnits(UPEm, GetInt16(table, 6, 1)); + } +} + +#ifdef TEST5 +void KernGlyphs(TrueTypeFont *ttf, sal_uInt16 *glyphs, int nglyphs, int wmode, KernData *kern) +{ + int i; + + if (!nglyphs || !glyphs || !kern) return; + + for (i = 0; i < nglyphs-1; i++) kern[i].x = kern[i].y = 0; + + switch (ttf->kerntype) { + case KT_APPLE_NEW: KernGlyphsPrim1(ttf, glyphs, nglyphs, wmode, kern); return; + case KT_MICROSOFT: KernGlyphsPrim2(ttf, glyphs, nglyphs, wmode, kern); return; + default: return; + } +} +#endif + +GlyphData *GetTTRawGlyphData(TrueTypeFont *ttf, sal_uInt32 glyphID) +{ + sal_uInt8 *glyf = getTable(ttf, O_glyf); + sal_uInt8 *hmtx = getTable(ttf, O_hmtx); + sal_uInt32 length; + ControlPoint *cp; + int i, n, m; + + if( glyphID >= ttf->nglyphs ) + return 0; + + /* #127161# check the glyph offsets */ + length = getTableSize( ttf, O_glyf ); + if( length < ttf->goffsets[ glyphID+1 ] ) + return 0; + + length = ttf->goffsets[glyphID+1] - ttf->goffsets[glyphID]; + + GlyphData* d = (GlyphData*)malloc(sizeof(GlyphData)); assert(d != 0); + + if (length > 0) { + sal_uInt8 *srcptr = glyf + ttf->goffsets[glyphID]; + d->ptr = (sal_uInt8*)malloc((length + 1) & ~1); assert(d->ptr != 0); + memcpy( d->ptr, srcptr, length ); + d->compflag = (GetInt16( srcptr, 0, 1 ) < 0); + } else { + d->ptr = 0; + d->compflag = 0; + } + + d->glyphID = glyphID; + d->nbytes = (sal_uInt16)((length + 1) & ~1); + + /* now calculate npoints and ncontours */ + n = GetTTGlyphPoints(ttf, glyphID, &cp); + if (n != -1) { + m = 0; + for (i = 0; i < n; i++) { + if (cp[i].flags & 0x8000) m++; + } + d->npoints = (sal_uInt16)n; + d->ncontours = (sal_uInt16)m; + free(cp); + } else { + d->npoints = 0; + d->ncontours = 0; + } + + /* get advance width and left sidebearing */ + if (glyphID < ttf->numberOfHMetrics) { + d->aw = GetUInt16(hmtx, 4 * glyphID, 1); + d->lsb = GetInt16(hmtx, 4 * glyphID + 2, 1); + } else { + d->aw = GetUInt16(hmtx, 4 * (ttf->numberOfHMetrics - 1), 1); + d->lsb = GetInt16(hmtx + ttf->numberOfHMetrics * 4, (glyphID - ttf->numberOfHMetrics) * 2, 1); + } + + return d; +} + +int GetTTNameRecords(TrueTypeFont *ttf, NameRecord **nr) +{ + sal_uInt8 *table = getTable(ttf, O_name); + int nTableSize = getTableSize(ttf, O_name ); + sal_uInt16 n = GetUInt16(table, 2, 1); + sal_uInt8* rec_string = NULL; + int nStrBase = GetUInt16(table, 4, 1); + NameRecord *rec; + int i; + + *nr = 0; + if (n == 0) return 0; + + rec = (NameRecord*)calloc(n, sizeof(NameRecord)); + + for (i = 0; i < n; i++) { + int nStrOffset = GetUInt16(table + 6, 10 + 12 * i, 1); + rec[i].platformID = GetUInt16(table + 6, 12 * i, 1); + rec[i].encodingID = GetUInt16(table + 6, 2 + 12 * i, 1); + rec[i].languageID = GetUInt16(table + 6, 4 + 12 * i, 1); + rec[i].nameID = GetUInt16(table + 6, 6 + 12 * i, 1); + rec[i].slen = GetUInt16(table + 6, 8 + 12 * i, 1); + if (rec[i].slen) { + if( nStrBase+nStrOffset+rec[i].slen >= nTableSize ) { + rec[i].sptr = 0; + rec[i].slen = 0; + continue; + } + + rec_string = table + nStrBase + nStrOffset; + // sanity check + if( rec_string > (sal_uInt8*)ttf->ptr && rec_string < ((sal_uInt8*)ttf->ptr + ttf->fsize - rec[i].slen ) ) + { + rec[i].sptr = (sal_uInt8 *) malloc(rec[i].slen); assert(rec[i].sptr != 0); + memcpy(rec[i].sptr, rec_string, rec[i].slen); + } + else + { +#ifdef DEBUG + fprintf( stderr, "found invalid name record %d with name id %d for file %s\n", + i, rec[i].nameID, ttf->fname ); +#endif + rec[i].sptr = 0; + rec[i].slen = 0; + } + } else { + rec[i].sptr = 0; + } + // some fonts have 3.0 names => fix them to 3.1 + if( (rec[i].platformID == 3) && (rec[i].encodingID == 0) ) + rec[i].encodingID = 1; + } + + *nr = rec; + return n; +} + +void DisposeNameRecords(NameRecord* nr, int n) +{ + int i; + for (i = 0; i < n; i++) { + if (nr[i].sptr) free(nr[i].sptr); + } + free(nr); +} + +} // namespace vcl + + +#ifdef TEST1 +/* This example creates a subset of a TrueType font with two encoded characters */ +int main(int ac, char **av) +{ + TrueTypeFont *fnt; + int r; + + /* Array of Unicode source characters */ + sal_uInt16 chars[2]; + + /* Encoding vector maps character encoding to the ordinal number + * of the glyph in the output file */ + sal_uInt8 encoding[2]; + + /* This array is for glyph IDs that source characters map to */ + sal_uInt16 g[2]; + + + if (ac < 2) return 0; + + if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { + fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); + return 0; + } + + + /* We want to create the output file that only contains two Unicode characters: + * L'a' and L'A' */ + + chars[0] = L'a'; + chars[1] = L'A'; + + /* Figure out what glyphs do these characters map in our font */ + MapString(fnt, chars, 2, g); + + /* Encode the characters. Value of encoding[i] is the number 0..255 which maps to glyph i of the + * newly generated font */ + encoding[0] = chars[0]; + encoding[1] = chars[1]; + + + /* Generate a subset */ + CreateT3FromTTGlyphs(fnt, stdout, 0, g, encoding, 2, 0); + + /* Now call the dtor for the font */ + CloseTTFont(fnt); + return 0; +} +#endif + +#ifdef TEST2 +/* This example extracts first 224 glyphs from a TT fonts and encodes them starting at 32 */ +int main(int ac, char **av) +{ + TrueTypeFont *fnt; + int i, r; + + /* Array of Unicode source characters */ + sal_uInt16 glyphs[224]; + + /* Encoding vector maps character encoding to the ordinal number + * of the glyph in the output file */ + sal_uInt8 encoding[224]; + + + + for (i=0; i<224; i++) { + glyphs[i] = i; + encoding[i] = 32 + i; + } + + if (ac < 2) return 0; + + if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { + fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); + return 0; + } + + + /* Encode the characters. Value of encoding[i] is the number 0..255 which maps to glyph i of the + * newly generated font */ + + /* Generate a subset */ + CreateT3FromTTGlyphs(fnt, stdout, 0, glyphs, encoding, 224, 0); + + /* Now call the dtor for the font */ + CloseTTFont(fnt); + return 0; +} +#endif + +#ifdef TEST3 +/* Glyph metrics example */ +int main(int ac, char **av) +{ + TrueTypeFont *fnt; + int i, r; + sal_uInt16 glyphs[224]; + TTSimpleGlyphMetrics *m; + + for (i=0; i<224; i++) { + glyphs[i] = i; + } + + if (ac < 2) return 0; + + if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { + fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); + return 0; + } + + if ((m = GetTTSimpleGlyphMetrics(fnt, glyphs, 224, 0)) == 0) { + printf("Requested metrics is not available\n"); + } else { + for (i=0; i<224; i++) { + printf("%d. advWid: %5d, LSBear: %5d\n", i, m[i].adv, m[i].sb); + } + } + + /* Now call the dtor for the font */ + free(m); + CloseTTFont(fnt); + return 0; +} +#endif + +#ifdef TEST4 +int main(int ac, char **av) +{ + TrueTypeFont *fnt; + TTGlobalFontInfo info; + int i, r; + + + if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { + fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); + return 0; + } + + printf("Font file: %s\n", av[1]); + +#ifdef PRINT_KERN + switch (fnt->kerntype) { + case KT_MICROSOFT: + printf("\tkern: MICROSOFT, ntables: %d.", fnt->nkern); + if (fnt->nkern) { + printf(" ["); + for (i=0; i<fnt->nkern; i++) { + printf("%04X ", GetUInt16(fnt->kerntables[i], 4, 1)); + } + printf("]"); + } + printf("\n"); + break; + + case KT_APPLE_NEW: + printf("\tkern: APPLE_NEW, ntables: %d.", fnt->nkern); + if (fnt->nkern) { + printf(" ["); + for (i=0; i<fnt->nkern; i++) { + printf("%04X ", GetUInt16(fnt->kerntables[i], 4, 1)); + } + printf("]"); + } + printf("\n"); + break; + + case KT_NONE: + printf("\tkern: none.\n"); + break; + + default: + printf("\tkern: unrecoginzed.\n"); + break; + } + printf("\n"); +#endif + + GetTTGlobalFontInfo(fnt, &info); + printf("\tfamily name: `%s`\n", info.family); + printf("\tsubfamily name: `%s`\n", info.subfamily); + printf("\tpostscript name: `%s`\n", info.psname); + printf("\tweight: %d\n", info.weight); + printf("\twidth: %d\n", info.width); + printf("\tpitch: %d\n", info.pitch); + printf("\titalic angle: %d\n", info.italicAngle); + printf("\tbouding box: [%d %d %d %d]\n", info.xMin, info.yMin, info.xMax, info.yMax); + printf("\tascender: %d\n", info.ascender); + printf("\tdescender: %d\n", info.descender); + printf("\tlinegap: %d\n", info.linegap); + printf("\tvascent: %d\n", info.vascent); + printf("\tvdescent: %d\n", info.vdescent); + printf("\ttypoAscender: %d\n", info.typoAscender); + printf("\ttypoDescender: %d\n", info.typoDescender); + printf("\ttypoLineGap: %d\n", info.typoLineGap); + printf("\twinAscent: %d\n", info.winAscent); + printf("\twinDescent: %d\n", info.winDescent); + printf("\tUnicode ranges:\n"); + for (i = 0; i < 32; i++) { + if ((info.ur1 >> i) & 1) { + printf("\t\t\t%s\n", UnicodeRangeName(i)); + } + } + for (i = 0; i < 32; i++) { + if ((info.ur2 >> i) & 1) { + printf("\t\t\t%s\n", UnicodeRangeName(i+32)); + } + } + for (i = 0; i < 32; i++) { + if ((info.ur3 >> i) & 1) { + printf("\t\t\t%s\n", UnicodeRangeName(i+64)); + } + } + for (i = 0; i < 32; i++) { + if ((info.ur4 >> i) & 1) { + printf("\t\t\t%s\n", UnicodeRangeName(i+96)); + } + } + + CloseTTFont(fnt); + return 0; +} +#endif + +#ifdef TEST5 +/* Kerning example */ +int main(int ac, char **av) +{ + TrueTypeFont *fnt; + sal_uInt16 g[224]; + KernData d[223]; + int r, i, k = 0; + + g[k++] = 11; + g[k++] = 36; + g[k++] = 11; + g[k++] = 98; + g[k++] = 11; + g[k++] = 144; + g[k++] = 41; + g[k++] = 171; + g[k++] = 51; + g[k++] = 15; + + if (ac < 2) return 0; + + if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { + fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); + return 0; + } + + KernGlyphs(fnt, g, k, 0, d); + + for (i = 0; i < k-1; i++) { + printf("%3d %3d: [%3d %3d]\n", g[i], g[i+1], d[i].x, d[i].y); + } + + CloseTTFont(fnt); + return 0; +} +#endif + + + +#ifdef TEST6 +/* This example extracts a single glyph from a font */ +int main(int ac, char **av) +{ + TrueTypeFont *fnt; + int r, i; + + sal_uInt16 glyphs[256]; + sal_uInt8 encoding[256]; + + for (i=0; i<256; i++) { + glyphs[i] = 512 + i; + encoding[i] = i; + } + +#if 0 + i=0; + glyphs[i++] = 2001; + glyphs[i++] = 2002; + glyphs[i++] = 2003; + glyphs[i++] = 2004; + glyphs[i++] = 2005; + glyphs[i++] = 2006; + glyphs[i++] = 2007; + glyphs[i++] = 2008; + glyphs[i++] = 2009; + glyphs[i++] = 2010; + glyphs[i++] = 2011; + glyphs[i++] = 2012; + glyphs[i++] = 2013; + glyphs[i++] = 2014; + glyphs[i++] = 2015; + glyphs[i++] = 2016; + glyphs[i++] = 2017; + glyphs[i++] = 2018; + glyphs[i++] = 2019; + glyphs[i++] = 2020; + + + r = 97; + i = 0; + encoding[i++] = r++; + encoding[i++] = r++; + encoding[i++] = r++; + encoding[i++] = r++; + encoding[i++] = r++; + encoding[i++] = r++; + encoding[i++] = r++; + encoding[i++] = r++; + encoding[i++] = r++; + encoding[i++] = r++; + encoding[i++] = r++; + encoding[i++] = r++; + encoding[i++] = r++; + encoding[i++] = r++; + encoding[i++] = r++; + encoding[i++] = r++; + encoding[i++] = r++; + encoding[i++] = r++; + encoding[i++] = r++; + encoding[i++] = r++; +#endif + + if (ac < 2) return 0; + + if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { + fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); + return 0; + } + + /* Generate a subset */ + CreateT3FromTTGlyphs(fnt, stdout, 0, glyphs, encoding, 256, 0); + + fprintf(stderr, "UnitsPerEm: %d.\n", fnt->unitsPerEm); + + /* Now call the dtor for the font */ + CloseTTFont(fnt); + return 0; +} +#endif + +#ifdef TEST7 +/* NameRecord extraction example */ +int main(int ac, char **av) +{ + TrueTypeFont *fnt; + int r, i, j, n; + NameRecord *nr; + + if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { + fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); + return 0; + } + + if ((n = GetTTNameRecords(fnt, &nr)) == 0) { + fprintf(stderr, "No name records in the font.\n"); + return 0; + } + + printf("Number of name records: %d.\n", n); + for (i = 0; i < n; i++) { + printf("%d %d %04X %d [", nr[i].platformID, nr[i].encodingID, nr[i].languageID, nr[i].nameID); + for (j=0; j<nr[i].slen; j++) { + printf("%c", isprint(nr[i].sptr[j]) ? nr[i].sptr[j] : '.'); + } + printf("]\n"); + } + + + DisposeNameRecords(nr, n); + CloseTTFont(fnt); + return 0; +} +#endif + +#ifdef TEST8 +/* TrueType -> TrueType subsetting */ +int main(int ac, char **av) +{ + TrueTypeFont *fnt; + sal_uInt16 glyphArray[] = { 0, 98, 99, 22, 24, 25, 26, 27, 28, 29, 30, 31, 1270, 1289, 34}; + sal_uInt8 encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}; + int r; + + if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { + fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); + return 0; + } + + CreateTTFromTTGlyphs(fnt, "subfont.ttf", glyphArray, encoding, 15, 0, 0, TTCF_AutoName | TTCF_IncludeOS2); + + + CloseTTFont(fnt); + + return 0; +} +#endif + +#ifdef TEST9 +/* TrueType -> Type42 subsetting */ +int main(int ac, char **av) +{ + TrueTypeFont *fnt; + /* + sal_uInt16 glyphArray[] = { 0, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34}; + sal_uInt8 encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}; + */ + sal_uInt16 glyphArray[] = { 0, 6711, 6724, 11133, 11144, 14360, 26, 27, 28, 29, 30, 31, 1270, 1289, 34}; + sal_uInt8 encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}; + int r; + + if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { + fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); + return 0; + } + + CreateT42FromTTGlyphs(fnt, stdout, "testfont", glyphArray, encoding, 15); + + CloseTTFont(fnt); + + return 0; +} +#endif + +#ifdef TEST10 +/* Component glyph test */ +int main(int ac, char **av) +{ + TrueTypeFont *fnt; + int r, i; + list glyphlist = listNewEmpty(); + + + if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { + fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); + return 0; + } + + for (i = 0; i < fnt->nglyphs; i++) { + r = GetTTGlyphComponents(fnt, i, glyphlist); + if (r > 1) { + printf("%d -> ", i); + listToFirst(glyphlist); + do { + printf("%d ", (int) listCurrent(glyphlist)); + } while (listNext(glyphlist)); + printf("\n"); + } else { + printf("%d: single glyph.\n", i); + } + listClear(glyphlist); + } + + CloseTTFont(fnt); + listDispose(glyphlist); + + return 0; +} +#endif + + diff --git a/vcl/source/fontsubset/ttcr.c b/vcl/source/fontsubset/ttcr.c deleted file mode 100644 index e8c9d8cf74e0..000000000000 --- a/vcl/source/fontsubset/ttcr.c +++ /dev/null @@ -1,1669 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: ttcr.c,v $ - * $Revision: 1.11 $ - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -/* $Id: ttcr.c,v 1.11 2008-04-11 10:16:51 rt Exp $ */ - -/* - * TrueTypeCreator method implementation - * - * @author: Alexander Gelfenbain - * - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#if OSL_DEBUG_LEVEL == 0 -# ifndef NDEBUG -# define NDEBUG -# endif -#endif -#include <assert.h> - -#include "ttcr.h" - -/* These must be #defined so that they can be used in initializers */ -#define T_maxp 0x6D617870 -#define T_glyf 0x676C7966 -#define T_head 0x68656164 -#define T_loca 0x6C6F6361 -#define T_name 0x6E616D65 -#define T_hhea 0x68686561 -#define T_hmtx 0x686D7478 -#define T_cmap 0x636D6170 -#define T_vhea 0x76686561 -#define T_vmtx 0x766D7478 -#define T_OS2 0x4F532F32 -#define T_post 0x706F7374 -#define T_kern 0x6B65726E -#define T_cvt 0x63767420 - -typedef struct { - sal_uInt32 tag; - sal_uInt32 length; - sal_uInt8 *data; -} TableEntry; - -/* - * this is a duplicate code from sft.c but it is left here for performance reasons - */ -#ifdef __GNUC__ -#define _inline static __inline__ -#else -#define _inline static -#endif - -_inline sal_uInt32 mkTag(sal_uInt8 a, sal_uInt8 b, sal_uInt8 c, sal_uInt8 d) { - return (a << 24) | (b << 16) | (c << 8) | d; -} - -/*- Data access macros for data stored in big-endian or little-endian format */ -_inline sal_Int16 GetInt16(const sal_uInt8 *ptr, sal_uInt32 offset, int bigendian) -{ - sal_Int16 t; - assert(ptr != 0); - - if (bigendian) { - t = (ptr+offset)[0] << 8 | (ptr+offset)[1]; - } else { - t = (ptr+offset)[1] << 8 | (ptr+offset)[0]; - } - - return t; -} - -_inline sal_uInt16 GetUInt16(const sal_uInt8 *ptr, sal_uInt32 offset, int bigendian) -{ - sal_uInt16 t; - assert(ptr != 0); - - if (bigendian) { - t = (ptr+offset)[0] << 8 | (ptr+offset)[1]; - } else { - t = (ptr+offset)[1] << 8 | (ptr+offset)[0]; - } - - return t; -} - -_inline sal_Int32 GetInt32(const sal_uInt8 *ptr, sal_uInt32 offset, int bigendian) -{ - sal_Int32 t; - assert(ptr != 0); - - if (bigendian) { - t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 | - (ptr+offset)[2] << 8 | (ptr+offset)[3]; - } else { - t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 | - (ptr+offset)[1] << 8 | (ptr+offset)[0]; - } - - return t; -} - -_inline sal_uInt32 GetUInt32(const sal_uInt8 *ptr, sal_uInt32 offset, int bigendian) -{ - sal_uInt32 t; - assert(ptr != 0); - - - if (bigendian) { - t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 | - (ptr+offset)[2] << 8 | (ptr+offset)[3]; - } else { - t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 | - (ptr+offset)[1] << 8 | (ptr+offset)[0]; - } - - return t; -} - - -_inline void PutInt16(sal_Int16 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian) -{ - assert(ptr != 0); - - if (bigendian) { - ptr[offset] = (sal_uInt8)((val >> 8) & 0xFF); - ptr[offset+1] = (sal_uInt8)(val & 0xFF); - } else { - ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF); - ptr[offset] = (sal_uInt8)(val & 0xFF); - } - -} - -_inline void PutUInt16(sal_uInt16 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian) -{ - assert(ptr != 0); - - if (bigendian) { - ptr[offset] = (sal_uInt8)((val >> 8) & 0xFF); - ptr[offset+1] = (sal_uInt8)(val & 0xFF); - } else { - ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF); - ptr[offset] = (sal_uInt8)(val & 0xFF); - } - -} - - -_inline void PutUInt32(sal_uInt32 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian) -{ - assert(ptr != 0); - - if (bigendian) { - ptr[offset] = (sal_uInt8)((val >> 24) & 0xFF); - ptr[offset+1] = (sal_uInt8)((val >> 16) & 0xFF); - ptr[offset+2] = (sal_uInt8)((val >> 8) & 0xFF); - ptr[offset+3] = (sal_uInt8)(val & 0xFF); - } else { - ptr[offset+3] = (sal_uInt8)((val >> 24) & 0xFF); - ptr[offset+2] = (sal_uInt8)((val >> 16) & 0xFF); - ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF); - ptr[offset] = (sal_uInt8)(val & 0xFF); - } - -} - - -_inline void PutInt32(sal_Int32 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian) -{ - assert(ptr != 0); - - if (bigendian) { - ptr[offset] = (sal_uInt8)((val >> 24) & 0xFF); - ptr[offset+1] = (sal_uInt8)((val >> 16) & 0xFF); - ptr[offset+2] = (sal_uInt8)((val >> 8) & 0xFF); - ptr[offset+3] = (sal_uInt8)(val & 0xFF); - } else { - ptr[offset+3] = (sal_uInt8)((val >> 24) & 0xFF); - ptr[offset+2] = (sal_uInt8)((val >> 16) & 0xFF); - ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF); - ptr[offset] = (sal_uInt8)(val & 0xFF); - } - -} - -static int TableEntryCompareF(const void *l, const void *r) -{ - return ((const TableEntry *) l)->tag - ((const TableEntry *) r)->tag; -} - -static int NameRecordCompareF(const void *l, const void *r) -{ - NameRecord *ll = (NameRecord *) l; - NameRecord *rr = (NameRecord *) r; - - if (ll->platformID != rr->platformID) { - return ll->platformID - rr->platformID; - } else if (ll->encodingID != rr->encodingID) { - return ll->encodingID - rr->encodingID; - } else if (ll->languageID != rr->languageID) { - return ll->languageID - rr->languageID; - } else if (ll->nameID != rr->nameID) { - return ll->nameID - rr->nameID; - } - return 0; -} - - -static sal_uInt32 CheckSum(sal_uInt32 *ptr, sal_uInt32 length) -{ - sal_uInt32 sum = 0; - sal_uInt32 *endptr = ptr + ((length + 3) & (sal_uInt32) ~3) / 4; - - while (ptr < endptr) sum += *ptr++; - - return sum; -} - -_inline void *smalloc(sal_uInt32 size) -{ - void *res = malloc(size); - assert(res != 0); - return res; -} - -_inline void *scalloc(sal_uInt32 n, sal_uInt32 size) -{ - void *res = calloc(n, size); - assert(res != 0); - return res; -} - -/* - * Public functions - */ - -void TrueTypeCreatorNewEmpty(sal_uInt32 tag, TrueTypeCreator **_this) -{ - TrueTypeCreator *ptr = smalloc(sizeof(TrueTypeCreator)); - - ptr->tables = listNewEmpty(); - listSetElementDtor(ptr->tables, (void(*)(void*))TrueTypeTableDispose); - - ptr->tag = tag; - - *_this = ptr; -} - -void TrueTypeCreatorDispose(TrueTypeCreator *_this) -{ - listDispose(_this->tables); - free(_this); -} - -int AddTable(TrueTypeCreator *_this, TrueTypeTable *table) -{ - if (table != 0) { - listAppend(_this->tables, table); - } - return SF_OK; -} - -void RemoveTable(TrueTypeCreator *_this, sal_uInt32 tag) -{ - int done = 0; - - if (listCount(_this->tables)) { - listToFirst(_this->tables); - do { - if (((TrueTypeTable *) listCurrent(_this->tables))->tag == tag) { - listRemove(_this->tables); - } else { - if (listNext(_this->tables)) { - done = 1; - } - } - } while (!done); - } -} - -static void ProcessTables(TrueTypeCreator *); - -int StreamToMemory(TrueTypeCreator *_this, sal_uInt8 **ptr, sal_uInt32 *length) -{ - sal_uInt16 numTables, searchRange=1, entrySelector=0, rangeShift; - sal_uInt32 s, offset, checkSumAdjustment = 0; - sal_uInt32 *p; - sal_uInt8 *ttf; - int i=0, n; - TableEntry *te; - sal_uInt8 *head = NULL; /* saved pointer to the head table data for checkSumAdjustment calculation */ - - if ((n = listCount(_this->tables)) == 0) return SF_TTFORMAT; - - ProcessTables(_this); - - /* ProcessTables() adds 'loca' and 'hmtx' */ - - n = listCount(_this->tables); - numTables = (sal_uInt16) n; - - - te = scalloc(n, sizeof(TableEntry)); - - listToFirst(_this->tables); - for (i = 0; i < n; i++) { - GetRawData((TrueTypeTable *) listCurrent(_this->tables), &te[i].data, &te[i].length, &te[i].tag); - listNext(_this->tables); - } - - qsort(te, n, sizeof(TableEntry), TableEntryCompareF); - - do { - searchRange *= 2; - entrySelector++; - } while (searchRange <= numTables); - - searchRange *= 8; - entrySelector--; - rangeShift = numTables * 16 - searchRange; - - s = offset = 12 + 16 * n; - - for (i = 0; i < n; i++) { - s += (te[i].length + 3) & (sal_uInt32) ~3; - /* if ((te[i].length & 3) != 0) s += (4 - (te[i].length & 3)) & 3; */ - } - - ttf = smalloc(s); - - /* Offset Table */ - PutUInt32(_this->tag, ttf, 0, 1); - PutUInt16(numTables, ttf, 4, 1); - PutUInt16(searchRange, ttf, 6, 1); - PutUInt16(entrySelector, ttf, 8, 1); - PutUInt16(rangeShift, ttf, 10, 1); - - /* Table Directory */ - for (i = 0; i < n; i++) { - PutUInt32(te[i].tag, ttf + 12, 16 * i, 1); - PutUInt32(CheckSum((sal_uInt32 *) te[i].data, te[i].length), ttf + 12, 16 * i + 4, 1); - PutUInt32(offset, ttf + 12, 16 * i + 8, 1); - PutUInt32(te[i].length, ttf + 12, 16 * i + 12, 1); - - if (te[i].tag == T_head) { - head = ttf + offset; - } - - memcpy(ttf+offset, te[i].data, (te[i].length + 3) & (sal_uInt32) ~3 ); - offset += (te[i].length + 3) & (sal_uInt32) ~3; - /* if ((te[i].length & 3) != 0) offset += (4 - (te[i].length & 3)) & 3; */ - } - - free(te); - - p = (sal_uInt32 *) ttf; - for (i = 0; i < (int)s / 4; i++) checkSumAdjustment += p[i]; - PutUInt32(0xB1B0AFBA - checkSumAdjustment, head, 8, 1); - - *ptr = ttf; - *length = s; - - return SF_OK; -} - -int StreamToFile(TrueTypeCreator *_this, const char* fname) -{ - sal_uInt8 *ptr; - sal_uInt32 length; - int r; - FILE* fd; - - if ((r = StreamToMemory(_this, &ptr, &length)) != SF_OK) return r; - if (!fname) return SF_BADFILE; - if ((fd = fopen(fname, "wb")) == NULL) return SF_BADFILE; - - if (fwrite(ptr, 1, length, fd) != length) { - r = SF_FILEIO; - } else { - r = SF_OK; - } - - fclose(fd); - free(ptr); - return r; -} - - - -/* - * TrueTypeTable private methods - */ - -#define TABLESIZE_head 54 -#define TABLESIZE_hhea 36 -#define TABLESIZE_maxp 32 - - - -/* Table data points to - * -------------------------------------------- - * generic tdata_generic struct - * 'head' TABLESIZE_head bytes of memory - * 'hhea' TABLESIZE_hhea bytes of memory - * 'loca' tdata_loca struct - * 'maxp' TABLESIZE_maxp bytes of memory - * 'glyf' list of GlyphData structs (defined in sft.h) - * 'name' list of NameRecord structs (defined in sft.h) - * 'post' tdata_post struct - * - */ - - -#define CMAP_SUBTABLE_INIT 10 -#define CMAP_SUBTABLE_INCR 10 -#define CMAP_PAIR_INIT 500 -#define CMAP_PAIR_INCR 500 - -typedef struct { - sal_uInt32 id; /* subtable ID (platform/encoding ID) */ - sal_uInt32 n; /* number of used translation pairs */ - sal_uInt32 m; /* number of allocated translation pairs */ - sal_uInt32 *xc; /* character array */ - sal_uInt32 *xg; /* glyph array */ -} CmapSubTable; - -typedef struct { - sal_uInt32 n; /* number of used CMAP sub-tables */ - sal_uInt32 m; /* number of allocated CMAP sub-tables */ - CmapSubTable *s; /* sotred array of sub-tables */ -} table_cmap; - -typedef struct { - sal_uInt32 tag; - sal_uInt32 nbytes; - sal_uInt8 *ptr; -} tdata_generic; - -typedef struct { - sal_uInt32 nbytes; /* number of bytes in loca table */ - sal_uInt8 *ptr; /* pointer to the data */ -} tdata_loca; - -typedef struct { - sal_uInt32 format; - sal_uInt32 italicAngle; - sal_Int16 underlinePosition; - sal_Int16 underlineThickness; - sal_uInt32 isFixedPitch; - void *ptr; /* format-specific pointer */ -} tdata_post; - - -/* allocate memory for a TT table */ -static sal_uInt8 *ttmalloc(sal_uInt32 nbytes) -{ - sal_uInt32 n; - sal_uInt8 *res; - - n = (nbytes + 3) & (sal_uInt32) ~3; - res = malloc(n); - assert(res != 0); - memset(res, 0, n); - - return res; -} - -static void FreeGlyphData(void *ptr) -{ - GlyphData *p = (GlyphData *) ptr; - if (p->ptr) free(p->ptr); - free(p); -} - -static void TrueTypeTableDispose_generic(TrueTypeTable *_this) -{ - if (_this) { - if (_this->data) { - tdata_generic *pdata = (tdata_generic *) _this->data; - if (pdata->nbytes) free(pdata->ptr); - free(_this->data); - } - free(_this); - } -} - -static void TrueTypeTableDispose_head(TrueTypeTable *_this) -{ - if (_this) { - if (_this->data) free(_this->data); - free(_this); - } -} - -static void TrueTypeTableDispose_hhea(TrueTypeTable *_this) -{ - if (_this) { - if (_this->data) free(_this->data); - free(_this); - } -} - -static void TrueTypeTableDispose_loca(TrueTypeTable *_this) -{ - if (_this) { - if (_this->data) { - tdata_loca *p = (tdata_loca *) _this->data; - if (p->ptr) free(p->ptr); - free(_this->data); - } - free(_this); - } -} - -static void TrueTypeTableDispose_maxp(TrueTypeTable *_this) -{ - if (_this) { - if (_this->data) free(_this->data); - free(_this); - } -} - -static void TrueTypeTableDispose_glyf(TrueTypeTable *_this) -{ - if (_this) { - if (_this->data) listDispose((list) _this->data); - free(_this); - } -} - -static void TrueTypeTableDispose_cmap(TrueTypeTable *_this) -{ - table_cmap *t; - CmapSubTable *s; - sal_uInt32 i; - - if (_this) { - t = (table_cmap *) _this->data; - if (t) { - s = t->s; - if (s) { - for (i = 0; i < t->m; i++) { - if (s[i].xc) free(s[i].xc); - if (s[i].xg) free(s[i].xg); - } - free(s); - } - free(t); - } - free(_this); - } -} - -static void TrueTypeTableDispose_name(TrueTypeTable *_this) -{ - if (_this) { - if (_this->data) listDispose((list) _this->data); - free(_this); - } -} - -static void TrueTypeTableDispose_post(TrueTypeTable *_this) -{ - if (_this) { - tdata_post *p = (tdata_post *) _this->data; - if (p) { - if (p->format == 0x00030000) { - /* do nothing */ - } else { - fprintf(stderr, "Unsupported format of a 'post' table: %08X.\n", (int)p->format); - } - free(p); - } - free(_this); - } -} - -/* destructor vtable */ - -static struct { - sal_uInt32 tag; - void (*f)(TrueTypeTable *); -} vtable1[] = -{ - {0, TrueTypeTableDispose_generic}, - {T_head, TrueTypeTableDispose_head}, - {T_hhea, TrueTypeTableDispose_hhea}, - {T_loca, TrueTypeTableDispose_loca}, - {T_maxp, TrueTypeTableDispose_maxp}, - {T_glyf, TrueTypeTableDispose_glyf}, - {T_cmap, TrueTypeTableDispose_cmap}, - {T_name, TrueTypeTableDispose_name}, - {T_post, TrueTypeTableDispose_post} - -}; - -static int GetRawData_generic(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) -{ - assert(_this != 0); - assert(_this->data != 0); - - *ptr = ((tdata_generic *) _this->data)->ptr; - *len = ((tdata_generic *) _this->data)->nbytes; - *tag = ((tdata_generic *) _this->data)->tag; - - return TTCR_OK; -} - - -static int GetRawData_head(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) -{ - *len = TABLESIZE_head; - *ptr = (sal_uInt8 *) _this->data; - *tag = T_head; - - return TTCR_OK; -} - -static int GetRawData_hhea(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) -{ - *len = TABLESIZE_hhea; - *ptr = (sal_uInt8 *) _this->data; - *tag = T_hhea; - - return TTCR_OK; -} - -static int GetRawData_loca(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) -{ - tdata_loca *p; - - assert(_this->data != 0); - - p = (tdata_loca *) _this->data; - - if (p->nbytes == 0) return TTCR_ZEROGLYPHS; - - *ptr = p->ptr; - *len = p->nbytes; - *tag = T_loca; - - return TTCR_OK; -} - -static int GetRawData_maxp(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) -{ - *len = TABLESIZE_maxp; - *ptr = (sal_uInt8 *) _this->data; - *tag = T_maxp; - - return TTCR_OK; -} - -static int GetRawData_glyf(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) -{ - sal_uInt32 n, nbytes = 0; - list l = (list) _this->data; - /* sal_uInt16 curID = 0; */ /* to check if glyph IDs are sequential and start from zero */ - sal_uInt8 *p; - - *ptr = 0; - *len = 0; - *tag = 0; - - if (listCount(l) == 0) return TTCR_ZEROGLYPHS; - - listToFirst(l); - do { - /* if (((GlyphData *) listCurrent(l))->glyphID != curID++) return TTCR_GLYPHSEQ; */ - nbytes += ((GlyphData *) listCurrent(l))->nbytes; - } while (listNext(l)); - - p = _this->rawdata = ttmalloc(nbytes); - - listToFirst(l); - do { - n = ((GlyphData *) listCurrent(l))->nbytes; - if (n != 0) { - memcpy(p, ((GlyphData *) listCurrent(l))->ptr, n); - p += n; - } - } while (listNext(l)); - - *len = nbytes; - *ptr = _this->rawdata; - *tag = T_glyf; - - return TTCR_OK; -} - -/* cmap packers */ -static sal_uInt8 *PackCmapType0(CmapSubTable *s, sal_uInt32 *length) -{ - sal_uInt8 *ptr = smalloc(262); - sal_uInt8 *p = ptr + 6; - sal_uInt32 i, j; - sal_uInt16 g; - - PutUInt16(0, ptr, 0, 1); - PutUInt16(262, ptr, 2, 1); - PutUInt16(0, ptr, 4, 1); - - for (i = 0; i < 256; i++) { - g = 0; - for (j = 0; j < s->n; j++) { - if (s->xc[j] == i) { - g = (sal_uInt16) s->xg[j]; - } - } - p[i] = (sal_uInt8) g; - } - *length = 262; - return ptr; -} - -static sal_uInt8 *PackCmapType6(CmapSubTable *s, sal_uInt32 *length) -{ - sal_uInt8 *ptr = smalloc(s->n*2 + 10); - sal_uInt8 *p = ptr + 10; - sal_uInt32 i, j; - sal_uInt16 g; - - PutUInt16(6, ptr, 0, 1); - PutUInt16((sal_uInt16)(s->n*2+10), ptr, 2, 1); - PutUInt16(0, ptr, 4, 1); - PutUInt16(0, ptr, 6, 1); - PutUInt16((sal_uInt16)(s->n), ptr, 8, 1 ); - - for (i = 0; i < s->n; i++) { - g = 0; - for (j = 0; j < s->n; j++) { - if (s->xc[j] == i) { - g = (sal_uInt16) s->xg[j]; - } - } - PutUInt16( g, p, 2*i, 1 ); - } - *length = s->n*2+10; - return ptr; -} - - - -/* XXX it only handles Format 0 encoding tables */ -static sal_uInt8 *PackCmap(CmapSubTable *s, sal_uInt32 *length) -{ - if( s->xg[s->n-1] > 0xff ) - return PackCmapType6(s, length); - else - return PackCmapType0(s, length); -} - -static int GetRawData_cmap(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) -{ - table_cmap *t; - sal_uInt8 **subtables; - sal_uInt32 *sizes; /* of subtables */ - sal_uInt32 i; - sal_uInt32 tlen = 0; - sal_uInt32 l; - sal_uInt32 cmapsize; - sal_uInt8 *cmap; - sal_uInt32 coffset; - - assert(_this != 0); - t = (table_cmap *) _this->data; - assert(t != 0); - assert(t->n != 0); - - subtables = scalloc(t->n, sizeof(sal_uInt8 *)); - sizes = scalloc(t->n, sizeof(sal_uInt32)); - - for (i = 0; i < t->n; i++) { - subtables[i] = PackCmap(t->s+i, &l); - sizes[i] = l; - tlen += l; - } - - cmapsize = tlen + 4 + 8 * t->n; - _this->rawdata = cmap = ttmalloc(cmapsize); - - PutUInt16(0, cmap, 0, 1); - PutUInt16((sal_uInt16)t->n, cmap, 2, 1); - coffset = 4 + t->n * 8; - - for (i = 0; i < t->n; i++) { - PutUInt16((sal_uInt16)(t->s[i].id >> 16), cmap + 4, i * 8, 1); - PutUInt16((sal_uInt16)(t->s[i].id & 0xFF), cmap + 4, 2 + i * 8, 1); - PutUInt32(coffset, cmap + 4, 4 + i * 8, 1); - memcpy(cmap + coffset, subtables[i], sizes[i]); - free(subtables[i]); - coffset += sizes[i]; - } - - free(subtables); - free(sizes); - - *ptr = cmap; - *len = cmapsize; - *tag = T_cmap; - - return TTCR_OK; -} - - -static int GetRawData_name(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) -{ - list l; - NameRecord *nr; - sal_Int16 i=0, n; /* number of Name Records */ - sal_uInt8 *name; - sal_uInt16 nameLen; - int stringLen = 0; - sal_uInt8 *p1, *p2; - - *ptr = 0; - *len = 0; - *tag = 0; - - assert(_this != 0); - l = (list) _this->data; - assert(l != 0); - - if ((n = (sal_Int16)listCount(l)) == 0) return TTCR_NONAMES; - - nr = scalloc(n, sizeof(NameRecord)); - - listToFirst(l); - - do { - memcpy(nr+i, listCurrent(l), sizeof(NameRecord)); - stringLen += nr[i].slen; - i++; - } while (listNext(l)); - - if (stringLen > 65535) { - free(nr); - return TTCR_NAMETOOLONG; - } - - qsort(nr, n, sizeof(NameRecord), NameRecordCompareF); - - nameLen = (sal_uInt16)(stringLen + 12 * n + 6); - name = ttmalloc(nameLen); - - PutUInt16(0, name, 0, 1); - PutUInt16(n, name, 2, 1); - PutUInt16((sal_uInt16)(6 + 12 * n), name, 4, 1); - - p1 = name + 6; - p2 = p1 + 12 * n; - - for (i = 0; i < n; i++) { - PutUInt16(nr[i].platformID, p1, 0, 1); - PutUInt16(nr[i].encodingID, p1, 2, 1); - PutUInt16(nr[i].languageID, p1, 4, 1); - PutUInt16(nr[i].nameID, p1, 6, 1); - PutUInt16(nr[i].slen, p1, 8, 1); - PutUInt16((sal_uInt16)(p2 - (name + 6 + 12 * n)), p1, 10, 1); - memcpy(p2, nr[i].sptr, nr[i].slen); - /* {int j; for(j=0; j<nr[i].slen; j++) printf("%c", nr[i].sptr[j]); printf("\n"); }; */ - p2 += nr[i].slen; - p1 += 12; - } - - free(nr); - _this->rawdata = name; - - *ptr = name; - *len = nameLen; - *tag = T_name; - - /*{int j; for(j=0; j<nameLen; j++) printf("%c", name[j]); }; */ - - return TTCR_OK; -} - -static int GetRawData_post(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) -{ - tdata_post *p = (tdata_post *) _this->data; - sal_uInt8 *post = 0; - sal_uInt32 postLen = 0; - int ret; - - if (_this->rawdata) free(_this->rawdata); - - if (p->format == 0x00030000) { - postLen = 32; - post = ttmalloc(postLen); - PutUInt32(0x00030000, post, 0, 1); - PutUInt32(p->italicAngle, post, 4, 1); - PutUInt16(p->underlinePosition, post, 8, 1); - PutUInt16(p->underlineThickness, post, 10, 1); - PutUInt16((sal_uInt16)p->isFixedPitch, post, 12, 1); - ret = TTCR_OK; - } else { - fprintf(stderr, "Unrecognized format of a post table: %08X.\n", (int)p->format); - ret = TTCR_POSTFORMAT; - } - - *ptr = _this->rawdata = post; - *len = postLen; - *tag = T_post; - - return ret; -} - - - - - -static struct { - sal_uInt32 tag; - int (*f)(TrueTypeTable *, sal_uInt8 **, sal_uInt32 *, sal_uInt32 *); -} vtable2[] = -{ - {0, GetRawData_generic}, - {T_head, GetRawData_head}, - {T_hhea, GetRawData_hhea}, - {T_loca, GetRawData_loca}, - {T_maxp, GetRawData_maxp}, - {T_glyf, GetRawData_glyf}, - {T_cmap, GetRawData_cmap}, - {T_name, GetRawData_name}, - {T_post, GetRawData_post} - - -}; - -/* - * TrueTypeTable public methods - */ - -/* Note: Type42 fonts only need these tables: - * head, hhea, loca, maxp, cvt, prep, glyf, hmtx, fpgm - * - * Microsoft required tables - * cmap, glyf, head, hhea, hmtx, loca, maxp, name, post, OS/2 - * - * Apple required tables - * cmap, glyf, head, hhea, hmtx, loca, maxp, name, post - * - */ - -TrueTypeTable *TrueTypeTableNew(sal_uInt32 tag, - sal_uInt32 nbytes, - sal_uInt8 *ptr) -{ - TrueTypeTable *table; - tdata_generic *pdata; - - table = smalloc(sizeof(TrueTypeTable)); - pdata = (tdata_generic *) smalloc(sizeof(tdata_generic)); - pdata->nbytes = nbytes; - pdata->tag = tag; - if (nbytes) { - pdata->ptr = ttmalloc(nbytes); - memcpy(pdata->ptr, ptr, nbytes); - } else { - pdata->ptr = 0; - } - - table->tag = 0; - table->data = pdata; - table->rawdata = 0; - - return table; -} - -TrueTypeTable *TrueTypeTableNew_head(sal_uInt32 fontRevision, - sal_uInt16 flags, - sal_uInt16 unitsPerEm, - sal_uInt8 *created, - sal_uInt16 macStyle, - sal_uInt16 lowestRecPPEM, - sal_Int16 fontDirectionHint) -{ - TrueTypeTable *table; - sal_uInt8 *ptr; - - assert(created != 0); - - table = smalloc(sizeof(TrueTypeTable)); - ptr = ttmalloc(TABLESIZE_head); - - - PutUInt32(0x00010000, ptr, 0, 1); /* version */ - PutUInt32(fontRevision, ptr, 4, 1); - PutUInt32(0x5F0F3CF5, ptr, 12, 1); /* magic number */ - PutUInt16(flags, ptr, 16, 1); - PutUInt16(unitsPerEm, ptr, 18, 1); - memcpy(ptr+20, created, 8); /* Created Long Date */ - memset(ptr+28, 0, 8); /* Modified Long Date */ - PutUInt16(macStyle, ptr, 44, 1); - PutUInt16(lowestRecPPEM, ptr, 46, 1); - PutUInt16(fontDirectionHint, ptr, 48, 1); - PutUInt16(0, ptr, 52, 1); /* glyph data format: 0 */ - - table->data = (void *) ptr; - table->tag = T_head; - table->rawdata = 0; - - return table; -} - -TrueTypeTable *TrueTypeTableNew_hhea(sal_Int16 ascender, - sal_Int16 descender, - sal_Int16 linegap, - sal_Int16 caretSlopeRise, - sal_Int16 caretSlopeRun) -{ - TrueTypeTable *table; - sal_uInt8 *ptr; - - table = smalloc(sizeof(TrueTypeTable)); - ptr = ttmalloc(TABLESIZE_hhea); - - PutUInt32(0x00010000, ptr, 0, 1); /* version */ - PutUInt16(ascender, ptr, 4, 1); - PutUInt16(descender, ptr, 6, 1); - PutUInt16(linegap, ptr, 8, 1); - PutUInt16(caretSlopeRise, ptr, 18, 1); - PutUInt16(caretSlopeRun, ptr, 20, 1); - PutUInt16(0, ptr, 22, 1); /* reserved 1 */ - PutUInt16(0, ptr, 24, 1); /* reserved 2 */ - PutUInt16(0, ptr, 26, 1); /* reserved 3 */ - PutUInt16(0, ptr, 28, 1); /* reserved 4 */ - PutUInt16(0, ptr, 30, 1); /* reserved 5 */ - PutUInt16(0, ptr, 32, 1); /* metricDataFormat */ - - table->data = (void *) ptr; - table->tag = T_hhea; - table->rawdata = 0; - - return table; -} - -TrueTypeTable *TrueTypeTableNew_loca(void) -{ - TrueTypeTable *table = smalloc(sizeof(TrueTypeTable)); - table->data = smalloc(sizeof(tdata_loca)); - - ((tdata_loca *)table->data)->nbytes = 0; - ((tdata_loca *)table->data)->ptr = 0; - - table->tag = T_loca; - table->rawdata = 0; - - return table; -} - -TrueTypeTable *TrueTypeTableNew_maxp(sal_uInt8 *maxp, int size) -{ - TrueTypeTable *table = smalloc(sizeof(TrueTypeTable)); - table->data = ttmalloc(TABLESIZE_maxp); - - if (maxp && size == TABLESIZE_maxp) { - memcpy(table->data, maxp, TABLESIZE_maxp); - } - - table->tag = T_maxp; - table->rawdata = 0; - - return table; -} - -TrueTypeTable *TrueTypeTableNew_glyf(void) -{ - TrueTypeTable *table = smalloc(sizeof(TrueTypeTable)); - list l = listNewEmpty(); - - assert(l != 0); - - listSetElementDtor(l, FreeGlyphData); - - table->data = l; - table->rawdata = 0; - table->tag = T_glyf; - - return table; -} - -TrueTypeTable *TrueTypeTableNew_cmap(void) -{ - TrueTypeTable *table = smalloc(sizeof(TrueTypeTable)); - table_cmap *cmap = smalloc(sizeof(table_cmap)); - - cmap->n = 0; - cmap->m = CMAP_SUBTABLE_INIT; - cmap->s = (CmapSubTable *) scalloc(CMAP_SUBTABLE_INIT, sizeof(CmapSubTable)); - memset(cmap->s, 0, sizeof(CmapSubTable) * CMAP_SUBTABLE_INIT); - - table->data = (table_cmap *) cmap; - - table->rawdata = 0; - table->tag = T_cmap; - - return table; -} - -static void DisposeNameRecord(void *ptr) -{ - if (ptr != 0) { - NameRecord *nr = (NameRecord *) ptr; - if (nr->sptr) free(nr->sptr); - free(ptr); - } -} - -static NameRecord* NameRecordNewCopy(NameRecord *nr) -{ - NameRecord *p = smalloc(sizeof(NameRecord)); - - memcpy(p, nr, sizeof(NameRecord)); - - if (p->slen) { - p->sptr = smalloc(p->slen); - memcpy(p->sptr, nr->sptr, p->slen); - } - - return p; -} - -TrueTypeTable *TrueTypeTableNew_name(int n, NameRecord *nr) -{ - TrueTypeTable *table = smalloc(sizeof(TrueTypeTable)); - list l = listNewEmpty(); - - assert(l != 0); - - listSetElementDtor(l, DisposeNameRecord); - - if (n != 0) { - int i; - for (i = 0; i < n; i++) { - listAppend(l, NameRecordNewCopy(nr+i)); - } - } - - table->data = l; - table->rawdata = 0; - table->tag = T_name; - - return table; -} - -TrueTypeTable *TrueTypeTableNew_post(sal_uInt32 format, - sal_uInt32 italicAngle, - sal_Int16 underlinePosition, - sal_Int16 underlineThickness, - sal_uInt32 isFixedPitch) -{ - TrueTypeTable *table; - tdata_post *post; - - assert(format == 0x00030000); /* Only format 3.0 is supported at this time */ - table = smalloc(sizeof(TrueTypeTable)); - post = smalloc(sizeof(tdata_post)); - - post->format = format; - post->italicAngle = italicAngle; - post->underlinePosition = underlinePosition; - post->underlineThickness = underlineThickness; - post->isFixedPitch = isFixedPitch; - post->ptr = 0; - - table->data = post; - table->rawdata = 0; - table->tag = T_post; - - return table; -} - - - -void TrueTypeTableDispose(TrueTypeTable *_this) -{ - /* XXX do a binary search */ - unsigned int i; - - assert(_this != 0); - - if (_this->rawdata) free(_this->rawdata); - - for(i=0; i < sizeof(vtable1)/sizeof(*vtable1); i++) { - if (_this->tag == vtable1[i].tag) { - vtable1[i].f(_this); - return; - } - } - assert(!"Unknown TrueType table.\n"); -} - -int GetRawData(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) -{ - /* XXX do a binary search */ - unsigned int i; - - assert(_this != 0); - assert(ptr != 0); - assert(len != 0); - assert(tag != 0); - - *ptr = 0; *len = 0; *tag = 0; - - if (_this->rawdata) { - free(_this->rawdata); - _this->rawdata = 0; - } - - for(i=0; i < sizeof(vtable2)/sizeof(*vtable2); i++) { - if (_this->tag == vtable2[i].tag) { - return vtable2[i].f(_this, ptr, len, tag); - } - } - - assert(!"Unknwon TrueType table.\n"); - return TTCR_UNKNOWN; -} - -void cmapAdd(TrueTypeTable *table, sal_uInt32 id, sal_uInt32 c, sal_uInt32 g) -{ - sal_uInt32 i, found; - table_cmap *t; - CmapSubTable *s; - - assert(table != 0); - assert(table->tag == T_cmap); - t = (table_cmap *) table->data; assert(t != 0); - s = t->s; assert(s != 0); - - found = 0; - - for (i = 0; i < t->n; i++) { - if (s[i].id == id) { - found = 1; - break; - } - } - - if (!found) { - if (t->n == t->m) { - CmapSubTable *tmp; - tmp = scalloc(t->m + CMAP_SUBTABLE_INCR, sizeof(CmapSubTable)); - memset(tmp, 0, t->m + CMAP_SUBTABLE_INCR * sizeof(CmapSubTable)); - memcpy(tmp, s, sizeof(CmapSubTable) * t->m); - t->m += CMAP_SUBTABLE_INCR; - free(s); - s = tmp; - t->s = s; - } - - for (i = 0; i < t->n; i++) { - if (s[i].id > id) break; - } - - if (i < t->n) { - memmove(s+i+1, s+i, t->n-i); - } - - t->n++; - - s[i].id = id; - s[i].n = 0; - s[i].m = CMAP_PAIR_INIT; - s[i].xc = scalloc(CMAP_PAIR_INIT, sizeof(sal_uInt32)); - s[i].xg = scalloc(CMAP_PAIR_INIT, sizeof(sal_uInt32)); - } - - if (s[i].n == s[i].m) { - sal_uInt32 *tmp1 = scalloc(s[i].m + CMAP_PAIR_INCR, sizeof(sal_uInt32)); - sal_uInt32 *tmp2 = scalloc(s[i].m + CMAP_PAIR_INCR, sizeof(sal_uInt32)); - assert(tmp1 != 0); - assert(tmp2 != 0); - memcpy(tmp1, s[i].xc, sizeof(sal_uInt32) * s[i].m); - memcpy(tmp2, s[i].xg, sizeof(sal_uInt32) * s[i].m); - s[i].m += CMAP_PAIR_INCR; - free(s[i].xc); - free(s[i].xg); - s[i].xc = tmp1; - s[i].xg = tmp2; - } - - s[i].xc[s[i].n] = c; - s[i].xg[s[i].n] = g; - s[i].n++; -} - -sal_uInt32 glyfAdd(TrueTypeTable *table, GlyphData *glyphdata, TrueTypeFont *fnt) -{ - list l; - sal_uInt32 currentID; - int ret, n, ncomponents; - list glyphlist; - GlyphData *gd; - - assert(table != 0); - assert(table->tag == T_glyf); - - if (!glyphdata) return (sal_uInt32)~0; - - glyphlist = listNewEmpty(); - - ncomponents = GetTTGlyphComponents(fnt, glyphdata->glyphID, glyphlist); - - l = (list) table->data; - if (listCount(l) > 0) { - listToLast(l); - ret = n = ((GlyphData *) listCurrent(l))->newID + 1; - } else { - ret = n = 0; - } - glyphdata->newID = n++; - listAppend(l, glyphdata); - - if (ncomponents > 1) { - listPositionAt(glyphlist, 1); /* glyphData->glyphID is always the first glyph on the list */ - do { - int found = 0; - currentID = (sal_uIntPtr) listCurrent(glyphlist); - /* XXX expensive! should be rewritten with sorted arrays! */ - listToFirst(l); - do { - if (((GlyphData *) listCurrent(l))->glyphID == currentID) { - found = 1; - break; - } - } while (listNext(l)); - - if (!found) { - gd = GetTTRawGlyphData(fnt, currentID); - gd->newID = n++; - listAppend(l, gd); - } - } while (listNext(glyphlist)); - } - - listDispose(glyphlist); - return ret; -} - -sal_uInt32 glyfCount(const TrueTypeTable *table) -{ - assert(table != 0); - assert(table->tag == T_glyf); - return listCount((list) table->data); -} - - -void nameAdd(TrueTypeTable *table, NameRecord *nr) -{ - list l; - - assert(table != 0); - assert(table->tag == T_name); - - l = (list) table->data; - - listAppend(l, NameRecordNewCopy(nr)); -} - -static TrueTypeTable *FindTable(TrueTypeCreator *tt, sal_uInt32 tag) -{ - if (listIsEmpty(tt->tables)) return 0; - - listToFirst(tt->tables); - - do { - if (((TrueTypeTable *) listCurrent(tt->tables))->tag == tag) { - return listCurrent(tt->tables); - } - } while (listNext(tt->tables)); - - return 0; -} - -/* This function processes all the tables and synchronizes them before creating - * the output TrueType stream. - * - * *** It adds two TrueType tables to the font: 'loca' and 'hmtx' *** - * - * It does: - * - * - Re-numbers glyph IDs and creates 'glyf', 'loca', and 'hmtx' tables. - * - Calculates xMin, yMin, xMax, and yMax and stores values in 'head' table. - * - Stores indexToLocFormat in 'head' - * - updates 'maxp' table - * - Calculates advanceWidthMax, minLSB, minRSB, xMaxExtent and numberOfHMetrics - * in 'hhea' table - * - */ -static void ProcessTables(TrueTypeCreator *tt) -{ - TrueTypeTable *glyf, *loca, *head, *maxp, *hhea; - list glyphlist; - sal_uInt32 nGlyphs, locaLen = 0, glyfLen = 0; - sal_Int16 xMin = 0, yMin = 0, xMax = 0, yMax = 0; - sal_uInt32 i = 0; - sal_Int16 indexToLocFormat; - sal_uInt8 *glyfPtr, *locaPtr, *hmtxPtr, *hheaPtr; - sal_uInt32 hmtxSize; - sal_uInt8 *p1, *p2; - sal_uInt16 maxPoints = 0, maxContours = 0, maxCompositePoints = 0, maxCompositeContours = 0; - TTSimpleGlyphMetrics *met; - int nlsb = 0; - sal_uInt32 *gid; /* array of old glyphIDs */ - - glyf = FindTable(tt, T_glyf); - glyphlist = (list) glyf->data; - nGlyphs = listCount(glyphlist); - assert(nGlyphs != 0); - gid = scalloc(nGlyphs, sizeof(sal_uInt32)); - - RemoveTable(tt, T_loca); - RemoveTable(tt, T_hmtx); - - /* XXX Need to make sure that composite glyphs do not break during glyph renumbering */ - - listToFirst(glyphlist); - do { - GlyphData *gd = (GlyphData *) listCurrent(glyphlist); - sal_Int16 z; - glyfLen += gd->nbytes; - /* XXX if (gd->nbytes & 1) glyfLen++; */ - - - assert(gd->newID == i); - gid[i++] = gd->glyphID; - /* gd->glyphID = i++; */ - - /* printf("IDs: %d %d.\n", gd->glyphID, gd->newID); */ - - if (gd->nbytes != 0) { - z = GetInt16(gd->ptr, 2, 1); - if (z < xMin) xMin = z; - - z = GetInt16(gd->ptr, 4, 1); - if (z < yMin) yMin = z; - - z = GetInt16(gd->ptr, 6, 1); - if (z > xMax) xMax = z; - - z = GetInt16(gd->ptr, 8, 1); - if (z > yMax) yMax = z; - } - - if (gd->compflag == 0) { /* non-composite glyph */ - if (gd->npoints > maxPoints) maxPoints = gd->npoints; - if (gd->ncontours > maxContours) maxContours = gd->ncontours; - } else { /* composite glyph */ - if (gd->npoints > maxCompositePoints) maxCompositePoints = gd->npoints; - if (gd->ncontours > maxCompositeContours) maxCompositeContours = gd->ncontours; - } - - } while (listNext(glyphlist)); - - indexToLocFormat = (glyfLen / 2 > 0xFFFF) ? 1 : 0; - locaLen = indexToLocFormat ? (nGlyphs + 1) << 2 : (nGlyphs + 1) << 1; - - glyfPtr = ttmalloc(glyfLen); - locaPtr = ttmalloc(locaLen); - met = scalloc(nGlyphs, sizeof(TTSimpleGlyphMetrics)); - i = 0; - - listToFirst(glyphlist); - p1 = glyfPtr; - p2 = locaPtr; - do { - GlyphData *gd = (GlyphData *) listCurrent(glyphlist); - - if (gd->compflag) { /* re-number all components */ - sal_uInt16 flags, index; - sal_uInt8 *ptr = gd->ptr + 10; - do { - sal_uInt32 j; - flags = GetUInt16(ptr, 0, 1); - index = GetUInt16(ptr, 2, 1); - /* XXX use the sorted array of old to new glyphID mapping and do a binary search */ - for (j = 0; j < nGlyphs; j++) { - if (gid[j] == index) { - break; - } - } - /* printf("X: %d -> %d.\n", index, j); */ - - PutUInt16((sal_uInt16) j, ptr, 2, 1); - - ptr += 4; - - if (flags & ARG_1_AND_2_ARE_WORDS) { - ptr += 4; - } else { - ptr += 2; - } - - if (flags & WE_HAVE_A_SCALE) { - ptr += 2; - } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) { - ptr += 4; - } else if (flags & WE_HAVE_A_TWO_BY_TWO) { - ptr += 8; - } - } while (flags & MORE_COMPONENTS); - } - - if (gd->nbytes != 0) { - memcpy(p1, gd->ptr, gd->nbytes); - } - if (indexToLocFormat == 1) { - PutUInt32(p1 - glyfPtr, p2, 0, 1); - p2 += 4; - } else { - PutUInt16((sal_uInt16)((p1 - glyfPtr) >> 1), p2, 0, 1); - p2 += 2; - } - p1 += gd->nbytes; - - /* fill the array of metrics */ - met[i].adv = gd->aw; - met[i].sb = gd->lsb; - i++; - } while (listNext(glyphlist)); - - free(gid); - - if (indexToLocFormat == 1) { - PutUInt32(p1 - glyfPtr, p2, 0, 1); - } else { - PutUInt16((sal_uInt16)((p1 - glyfPtr) >> 1), p2, 0, 1); - } - - glyf->rawdata = glyfPtr; - - loca = TrueTypeTableNew_loca(); assert(loca != 0); - ((tdata_loca *) loca->data)->ptr = locaPtr; - ((tdata_loca *) loca->data)->nbytes = locaLen; - - AddTable(tt, loca); - - head = FindTable(tt, T_head); - PutInt16(xMin, head->data, 36, 1); - PutInt16(yMin, head->data, 38, 1); - PutInt16(xMax, head->data, 40, 1); - PutInt16(yMax, head->data, 42, 1); - PutInt16(indexToLocFormat, head->data, 50, 1); - - maxp = FindTable(tt, T_maxp); - - PutUInt16((sal_uInt16)nGlyphs, maxp->data, 4, 1); - PutUInt16(maxPoints, maxp->data, 6, 1); - PutUInt16(maxContours, maxp->data, 8, 1); - PutUInt16(maxCompositePoints, maxp->data, 10, 1); - PutUInt16(maxCompositeContours, maxp->data, 12, 1); - -#if 0 - /* XXX do not overwrite the existing data. Fix: re-calculate these numbers here */ - PutUInt16(2, maxp->data, 14, 1); /* maxZones is always 2 */ - PutUInt16(0, maxp->data, 16, 1); /* maxTwilightPoints */ - PutUInt16(0, maxp->data, 18, 1); /* maxStorage */ - PutUInt16(0, maxp->data, 20, 1); /* maxFunctionDefs */ - PutUint16(0, maxp->data, 22, 1); /* maxInstructionDefs */ - PutUint16(0, maxp->data, 24, 1); /* maxStackElements */ - PutUint16(0, maxp->data, 26, 1); /* maxSizeOfInstructions */ - PutUint16(0, maxp->data, 28, 1); /* maxComponentElements */ - PutUint16(0, maxp->data, 30, 1); /* maxComponentDepth */ -#endif - - /* - * Generate an htmx table and update hhea table - */ - hhea = FindTable(tt, T_hhea); assert(hhea != 0); - hheaPtr = (sal_uInt8 *) hhea->data; - if (nGlyphs > 2) { - for (i = nGlyphs - 1; i > 0; i--) { - if (met[i].adv != met[i-1].adv) break; - } - nlsb = nGlyphs - 1 - i; - } - hmtxSize = (nGlyphs - nlsb) * 4 + nlsb * 2; - hmtxPtr = ttmalloc(hmtxSize); - p1 = hmtxPtr; - - for (i = 0; i < nGlyphs; i++) { - if (i < nGlyphs - nlsb) { - PutUInt16(met[i].adv, p1, 0, 1); - PutUInt16(met[i].sb, p1, 2, 1); - p1 += 4; - } else { - PutUInt16(met[i].sb, p1, 0, 1); - p1 += 2; - } - } - - AddTable(tt, TrueTypeTableNew(T_hmtx, hmtxSize, hmtxPtr)); - PutUInt16((sal_uInt16)(nGlyphs - nlsb), hheaPtr, 34, 1); - free(hmtxPtr); - free(met); -} - -#ifdef TEST_TTCR -int main(void) -{ - TrueTypeCreator *ttcr; - sal_uInt8 *t1, *t2, *t3, *t4, *t5, *t6, *t7; - - TrueTypeCreatorNewEmpty(mkTag('t','r','u','e'), &ttcr); - - t1 = malloc(1000); memset(t1, 'a', 1000); - t2 = malloc(2000); memset(t2, 'b', 2000); - t3 = malloc(3000); memset(t3, 'c', 3000); - t4 = malloc(4000); memset(t4, 'd', 4000); - t5 = malloc(5000); memset(t5, 'e', 5000); - t6 = malloc(6000); memset(t6, 'f', 6000); - t7 = malloc(7000); memset(t7, 'g', 7000); - - AddTable(ttcr, TrueTypeTableNew(0x6D617870, 1000, t1)); - AddTable(ttcr, TrueTypeTableNew(0x4F532F32, 2000, t2)); - AddTable(ttcr, TrueTypeTableNew(0x636D6170, 3000, t3)); - AddTable(ttcr, TrueTypeTableNew(0x6C6F6361, 4000, t4)); - AddTable(ttcr, TrueTypeTableNew(0x68686561, 5000, t5)); - AddTable(ttcr, TrueTypeTableNew(0x676C7966, 6000, t6)); - AddTable(ttcr, TrueTypeTableNew(0x6B65726E, 7000, t7)); - - free(t1); - free(t2); - free(t3); - free(t4); - free(t5); - free(t6); - free(t7); - - - StreamToFile(ttcr, "ttcrout.ttf"); - - TrueTypeCreatorDispose(ttcr); - return 0; -} -#endif diff --git a/vcl/source/fontsubset/ttcr.cxx b/vcl/source/fontsubset/ttcr.cxx new file mode 100644 index 000000000000..7f9ae796142b --- /dev/null +++ b/vcl/source/fontsubset/ttcr.cxx @@ -0,0 +1,1669 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +/* + * TrueTypeCreator method implementation + * + * @author: Alexander Gelfenbain + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#if OSL_DEBUG_LEVEL == 0 +# ifndef NDEBUG +# define NDEBUG +# endif +#endif +#include <assert.h> + +#include "ttcr.hxx" +#include "list.h" + + + +namespace vcl +{ + +/* + * Private Data Types + */ + + struct _TrueTypeCreator { + sal_uInt32 tag; /**< TrueType file tag */ + list tables; /**< List of table tags and pointers */ + }; + +/* These must be #defined so that they can be used in initializers */ +#define T_maxp 0x6D617870 +#define T_glyf 0x676C7966 +#define T_head 0x68656164 +#define T_loca 0x6C6F6361 +#define T_name 0x6E616D65 +#define T_hhea 0x68686561 +#define T_hmtx 0x686D7478 +#define T_cmap 0x636D6170 +#define T_vhea 0x76686561 +#define T_vmtx 0x766D7478 +#define T_OS2 0x4F532F32 +#define T_post 0x706F7374 +#define T_kern 0x6B65726E +#define T_cvt 0x63767420 + +typedef struct { + sal_uInt32 tag; + sal_uInt32 length; + sal_uInt8 *data; +} TableEntry; + +/* + * this is a duplicate code from sft.c but it is left here for performance reasons + */ +#ifdef __GNUC__ +#define _inline static __inline__ +#else +#define _inline static +#endif + +_inline sal_uInt32 mkTag(sal_uInt8 a, sal_uInt8 b, sal_uInt8 c, sal_uInt8 d) { + return (a << 24) | (b << 16) | (c << 8) | d; +} + +/*- Data access macros for data stored in big-endian or little-endian format */ +_inline sal_Int16 GetInt16(const sal_uInt8 *ptr, sal_uInt32 offset, int bigendian) +{ + sal_Int16 t; + assert(ptr != 0); + + if (bigendian) { + t = (ptr+offset)[0] << 8 | (ptr+offset)[1]; + } else { + t = (ptr+offset)[1] << 8 | (ptr+offset)[0]; + } + + return t; +} + +_inline sal_uInt16 GetUInt16(const sal_uInt8 *ptr, sal_uInt32 offset, int bigendian) +{ + sal_uInt16 t; + assert(ptr != 0); + + if (bigendian) { + t = (ptr+offset)[0] << 8 | (ptr+offset)[1]; + } else { + t = (ptr+offset)[1] << 8 | (ptr+offset)[0]; + } + + return t; +} + +_inline sal_Int32 GetInt32(const sal_uInt8 *ptr, sal_uInt32 offset, int bigendian) +{ + sal_Int32 t; + assert(ptr != 0); + + if (bigendian) { + t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 | + (ptr+offset)[2] << 8 | (ptr+offset)[3]; + } else { + t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 | + (ptr+offset)[1] << 8 | (ptr+offset)[0]; + } + + return t; +} + +_inline sal_uInt32 GetUInt32(const sal_uInt8 *ptr, sal_uInt32 offset, int bigendian) +{ + sal_uInt32 t; + assert(ptr != 0); + + + if (bigendian) { + t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 | + (ptr+offset)[2] << 8 | (ptr+offset)[3]; + } else { + t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 | + (ptr+offset)[1] << 8 | (ptr+offset)[0]; + } + + return t; +} + + +_inline void PutInt16(sal_Int16 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian) +{ + assert(ptr != 0); + + if (bigendian) { + ptr[offset] = (sal_uInt8)((val >> 8) & 0xFF); + ptr[offset+1] = (sal_uInt8)(val & 0xFF); + } else { + ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF); + ptr[offset] = (sal_uInt8)(val & 0xFF); + } +} + +_inline void PutUInt16(sal_uInt16 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian) +{ + assert(ptr != 0); + + if (bigendian) { + ptr[offset] = (sal_uInt8)((val >> 8) & 0xFF); + ptr[offset+1] = (sal_uInt8)(val & 0xFF); + } else { + ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF); + ptr[offset] = (sal_uInt8)(val & 0xFF); + } +} + +_inline void PutUInt32(sal_uInt32 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian) +{ + assert(ptr != 0); + + if (bigendian) { + ptr[offset] = (sal_uInt8)((val >> 24) & 0xFF); + ptr[offset+1] = (sal_uInt8)((val >> 16) & 0xFF); + ptr[offset+2] = (sal_uInt8)((val >> 8) & 0xFF); + ptr[offset+3] = (sal_uInt8)(val & 0xFF); + } else { + ptr[offset+3] = (sal_uInt8)((val >> 24) & 0xFF); + ptr[offset+2] = (sal_uInt8)((val >> 16) & 0xFF); + ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF); + ptr[offset] = (sal_uInt8)(val & 0xFF); + } + +} + + +_inline void PutInt32(sal_Int32 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian) +{ + assert(ptr != 0); + + if (bigendian) { + ptr[offset] = (sal_uInt8)((val >> 24) & 0xFF); + ptr[offset+1] = (sal_uInt8)((val >> 16) & 0xFF); + ptr[offset+2] = (sal_uInt8)((val >> 8) & 0xFF); + ptr[offset+3] = (sal_uInt8)(val & 0xFF); + } else { + ptr[offset+3] = (sal_uInt8)((val >> 24) & 0xFF); + ptr[offset+2] = (sal_uInt8)((val >> 16) & 0xFF); + ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF); + ptr[offset] = (sal_uInt8)(val & 0xFF); + } + +} + +static int TableEntryCompareF(const void *l, const void *r) +{ + return ((const TableEntry *) l)->tag - ((const TableEntry *) r)->tag; +} + +static int NameRecordCompareF(const void *l, const void *r) +{ + NameRecord *ll = (NameRecord *) l; + NameRecord *rr = (NameRecord *) r; + + if (ll->platformID != rr->platformID) { + return ll->platformID - rr->platformID; + } else if (ll->encodingID != rr->encodingID) { + return ll->encodingID - rr->encodingID; + } else if (ll->languageID != rr->languageID) { + return ll->languageID - rr->languageID; + } else if (ll->nameID != rr->nameID) { + return ll->nameID - rr->nameID; + } + return 0; +} + + +static sal_uInt32 CheckSum(sal_uInt32 *ptr, sal_uInt32 length) +{ + sal_uInt32 sum = 0; + sal_uInt32 *endptr = ptr + ((length + 3) & (sal_uInt32) ~3) / 4; + + while (ptr < endptr) sum += *ptr++; + + return sum; +} + +_inline void *smalloc(sal_uInt32 size) +{ + void *res = malloc(size); + assert(res != 0); + return res; +} + +_inline void *scalloc(sal_uInt32 n, sal_uInt32 size) +{ + void *res = calloc(n, size); + assert(res != 0); + return res; +} + +/* + * Public functions + */ + +void TrueTypeCreatorNewEmpty(sal_uInt32 tag, TrueTypeCreator **_this) +{ + TrueTypeCreator* ptr = (TrueTypeCreator*)smalloc(sizeof(TrueTypeCreator)); + + ptr->tables = listNewEmpty(); + listSetElementDtor(ptr->tables, (list_destructor)TrueTypeTableDispose); + + ptr->tag = tag; + + *_this = ptr; +} + +int AddTable(TrueTypeCreator *_this, TrueTypeTable *table) +{ + if (table != 0) { + listAppend(_this->tables, table); + } + return SF_OK; +} + +void RemoveTable(TrueTypeCreator *_this, sal_uInt32 tag) +{ + int done = 0; + + if (listCount(_this->tables)) { + listToFirst(_this->tables); + do { + if (((TrueTypeTable *) listCurrent(_this->tables))->tag == tag) { + listRemove(_this->tables); + } else { + if (listNext(_this->tables)) { + done = 1; + } + } + } while (!done); + } +} + +static void ProcessTables(TrueTypeCreator *); + +int StreamToMemory(TrueTypeCreator *_this, sal_uInt8 **ptr, sal_uInt32 *length) +{ + sal_uInt16 numTables, searchRange=1, entrySelector=0, rangeShift; + sal_uInt32 s, offset, checkSumAdjustment = 0; + sal_uInt32 *p; + int i=0, n; + sal_uInt8 *head = NULL; /* saved pointer to the head table data for checkSumAdjustment calculation */ + + if ((n = listCount(_this->tables)) == 0) return SF_TTFORMAT; + + ProcessTables(_this); + + /* ProcessTables() adds 'loca' and 'hmtx' */ + + n = listCount(_this->tables); + numTables = (sal_uInt16) n; + + + TableEntry* te = (TableEntry*)scalloc(n, sizeof(TableEntry)); + + listToFirst(_this->tables); + for (i = 0; i < n; i++) { + GetRawData((TrueTypeTable *) listCurrent(_this->tables), &te[i].data, &te[i].length, &te[i].tag); + listNext(_this->tables); + } + + qsort(te, n, sizeof(TableEntry), TableEntryCompareF); + + do { + searchRange *= 2; + entrySelector++; + } while (searchRange <= numTables); + + searchRange *= 8; + entrySelector--; + rangeShift = numTables * 16 - searchRange; + + s = offset = 12 + 16 * n; + + for (i = 0; i < n; i++) { + s += (te[i].length + 3) & (sal_uInt32) ~3; + /* if ((te[i].length & 3) != 0) s += (4 - (te[i].length & 3)) & 3; */ + } + + sal_uInt8* ttf = (sal_uInt8*)smalloc(s); + + /* Offset Table */ + PutUInt32(_this->tag, ttf, 0, 1); + PutUInt16(numTables, ttf, 4, 1); + PutUInt16(searchRange, ttf, 6, 1); + PutUInt16(entrySelector, ttf, 8, 1); + PutUInt16(rangeShift, ttf, 10, 1); + + /* Table Directory */ + for (i = 0; i < n; i++) { + PutUInt32(te[i].tag, ttf + 12, 16 * i, 1); + PutUInt32(CheckSum((sal_uInt32 *) te[i].data, te[i].length), ttf + 12, 16 * i + 4, 1); + PutUInt32(offset, ttf + 12, 16 * i + 8, 1); + PutUInt32(te[i].length, ttf + 12, 16 * i + 12, 1); + + if (te[i].tag == T_head) { + head = ttf + offset; + } + + memcpy(ttf+offset, te[i].data, (te[i].length + 3) & (sal_uInt32) ~3 ); + offset += (te[i].length + 3) & (sal_uInt32) ~3; + /* if ((te[i].length & 3) != 0) offset += (4 - (te[i].length & 3)) & 3; */ + } + + free(te); + + p = (sal_uInt32 *) ttf; + for (i = 0; i < (int)s / 4; i++) checkSumAdjustment += p[i]; + PutUInt32(0xB1B0AFBA - checkSumAdjustment, head, 8, 1); + + *ptr = ttf; + *length = s; + + return SF_OK; +} + +int StreamToFile(TrueTypeCreator *_this, const char* fname) +{ + sal_uInt8 *ptr; + sal_uInt32 length; + int r; + FILE* fd; + + if ((r = StreamToMemory(_this, &ptr, &length)) != SF_OK) return r; + if (!fname) return SF_BADFILE; + if ((fd = fopen(fname, "wb")) == NULL) return SF_BADFILE; + + if (fwrite(ptr, 1, length, fd) != length) { + r = SF_FILEIO; + } else { + r = SF_OK; + } + + fclose(fd); + free(ptr); + return r; +} + + + +/* + * TrueTypeTable private methods + */ + +#define TABLESIZE_head 54 +#define TABLESIZE_hhea 36 +#define TABLESIZE_maxp 32 + + + +/* Table data points to + * -------------------------------------------- + * generic tdata_generic struct + * 'head' TABLESIZE_head bytes of memory + * 'hhea' TABLESIZE_hhea bytes of memory + * 'loca' tdata_loca struct + * 'maxp' TABLESIZE_maxp bytes of memory + * 'glyf' list of GlyphData structs (defined in sft.h) + * 'name' list of NameRecord structs (defined in sft.h) + * 'post' tdata_post struct + * + */ + + +#define CMAP_SUBTABLE_INIT 10 +#define CMAP_SUBTABLE_INCR 10 +#define CMAP_PAIR_INIT 500 +#define CMAP_PAIR_INCR 500 + +typedef struct { + sal_uInt32 id; /* subtable ID (platform/encoding ID) */ + sal_uInt32 n; /* number of used translation pairs */ + sal_uInt32 m; /* number of allocated translation pairs */ + sal_uInt32 *xc; /* character array */ + sal_uInt32 *xg; /* glyph array */ +} CmapSubTable; + +typedef struct { + sal_uInt32 n; /* number of used CMAP sub-tables */ + sal_uInt32 m; /* number of allocated CMAP sub-tables */ + CmapSubTable *s; /* sotred array of sub-tables */ +} table_cmap; + +typedef struct { + sal_uInt32 tag; + sal_uInt32 nbytes; + sal_uInt8 *ptr; +} tdata_generic; + +typedef struct { + sal_uInt32 nbytes; /* number of bytes in loca table */ + sal_uInt8 *ptr; /* pointer to the data */ +} tdata_loca; + +typedef struct { + sal_uInt32 format; + sal_uInt32 italicAngle; + sal_Int16 underlinePosition; + sal_Int16 underlineThickness; + sal_uInt32 isFixedPitch; + void *ptr; /* format-specific pointer */ +} tdata_post; + + +/* allocate memory for a TT table */ +static sal_uInt8 *ttmalloc(sal_uInt32 nbytes) +{ + sal_uInt32 n; + + n = (nbytes + 3) & (sal_uInt32) ~3; + sal_uInt8* res = (sal_uInt8*)malloc(n); + assert(res != 0); + memset(res, 0, n); + + return res; +} + +static void FreeGlyphData(void *ptr) +{ + GlyphData *p = (GlyphData *) ptr; + if (p->ptr) free(p->ptr); + free(p); +} + +static void TrueTypeTableDispose_generic(TrueTypeTable *_this) +{ + if (_this) { + if (_this->data) { + tdata_generic *pdata = (tdata_generic *) _this->data; + if (pdata->nbytes) free(pdata->ptr); + free(_this->data); + } + free(_this); + } +} + +static void TrueTypeTableDispose_head(TrueTypeTable *_this) +{ + if (_this) { + if (_this->data) free(_this->data); + free(_this); + } +} + +static void TrueTypeTableDispose_hhea(TrueTypeTable *_this) +{ + if (_this) { + if (_this->data) free(_this->data); + free(_this); + } +} + +static void TrueTypeTableDispose_loca(TrueTypeTable *_this) +{ + if (_this) { + if (_this->data) { + tdata_loca *p = (tdata_loca *) _this->data; + if (p->ptr) free(p->ptr); + free(_this->data); + } + free(_this); + } +} + +static void TrueTypeTableDispose_maxp(TrueTypeTable *_this) +{ + if (_this) { + if (_this->data) free(_this->data); + free(_this); + } +} + +static void TrueTypeTableDispose_glyf(TrueTypeTable *_this) +{ + if (_this) { + if (_this->data) listDispose((list) _this->data); + free(_this); + } +} + +static void TrueTypeTableDispose_cmap(TrueTypeTable *_this) +{ + table_cmap *t; + CmapSubTable *s; + sal_uInt32 i; + + if (_this) { + t = (table_cmap *) _this->data; + if (t) { + s = t->s; + if (s) { + for (i = 0; i < t->m; i++) { + if (s[i].xc) free(s[i].xc); + if (s[i].xg) free(s[i].xg); + } + free(s); + } + free(t); + } + free(_this); + } +} + +static void TrueTypeTableDispose_name(TrueTypeTable *_this) +{ + if (_this) { + if (_this->data) listDispose((list) _this->data); + free(_this); + } +} + +static void TrueTypeTableDispose_post(TrueTypeTable *_this) +{ + if (_this) { + tdata_post *p = (tdata_post *) _this->data; + if (p) { + if (p->format == 0x00030000) { + /* do nothing */ + } else { + fprintf(stderr, "Unsupported format of a 'post' table: %08X.\n", (int)p->format); + } + free(p); + } + free(_this); + } +} + +/* destructor vtable */ + +static struct { + sal_uInt32 tag; + void (*f)(TrueTypeTable *); +} vtable1[] = +{ + {0, TrueTypeTableDispose_generic}, + {T_head, TrueTypeTableDispose_head}, + {T_hhea, TrueTypeTableDispose_hhea}, + {T_loca, TrueTypeTableDispose_loca}, + {T_maxp, TrueTypeTableDispose_maxp}, + {T_glyf, TrueTypeTableDispose_glyf}, + {T_cmap, TrueTypeTableDispose_cmap}, + {T_name, TrueTypeTableDispose_name}, + {T_post, TrueTypeTableDispose_post} + +}; + +static int GetRawData_generic(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) +{ + assert(_this != 0); + assert(_this->data != 0); + + *ptr = ((tdata_generic *) _this->data)->ptr; + *len = ((tdata_generic *) _this->data)->nbytes; + *tag = ((tdata_generic *) _this->data)->tag; + + return TTCR_OK; +} + + +static int GetRawData_head(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) +{ + *len = TABLESIZE_head; + *ptr = (sal_uInt8 *) _this->data; + *tag = T_head; + + return TTCR_OK; +} + +static int GetRawData_hhea(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) +{ + *len = TABLESIZE_hhea; + *ptr = (sal_uInt8 *) _this->data; + *tag = T_hhea; + + return TTCR_OK; +} + +static int GetRawData_loca(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) +{ + tdata_loca *p; + + assert(_this->data != 0); + + p = (tdata_loca *) _this->data; + + if (p->nbytes == 0) return TTCR_ZEROGLYPHS; + + *ptr = p->ptr; + *len = p->nbytes; + *tag = T_loca; + + return TTCR_OK; +} + +static int GetRawData_maxp(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) +{ + *len = TABLESIZE_maxp; + *ptr = (sal_uInt8 *) _this->data; + *tag = T_maxp; + + return TTCR_OK; +} + +static int GetRawData_glyf(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) +{ + sal_uInt32 n, nbytes = 0; + list l = (list) _this->data; + /* sal_uInt16 curID = 0; */ /* to check if glyph IDs are sequential and start from zero */ + sal_uInt8 *p; + + *ptr = 0; + *len = 0; + *tag = 0; + + if (listCount(l) == 0) return TTCR_ZEROGLYPHS; + + listToFirst(l); + do { + /* if (((GlyphData *) listCurrent(l))->glyphID != curID++) return TTCR_GLYPHSEQ; */ + nbytes += ((GlyphData *) listCurrent(l))->nbytes; + } while (listNext(l)); + + p = _this->rawdata = ttmalloc(nbytes); + + listToFirst(l); + do { + n = ((GlyphData *) listCurrent(l))->nbytes; + if (n != 0) { + memcpy(p, ((GlyphData *) listCurrent(l))->ptr, n); + p += n; + } + } while (listNext(l)); + + *len = nbytes; + *ptr = _this->rawdata; + *tag = T_glyf; + + return TTCR_OK; +} + +/* cmap packers */ +static sal_uInt8 *PackCmapType0(CmapSubTable *s, sal_uInt32 *length) +{ + sal_uInt8* ptr = (sal_uInt8*)smalloc(262); + sal_uInt8 *p = ptr + 6; + sal_uInt32 i, j; + sal_uInt16 g; + + PutUInt16(0, ptr, 0, 1); + PutUInt16(262, ptr, 2, 1); + PutUInt16(0, ptr, 4, 1); + + for (i = 0; i < 256; i++) { + g = 0; + for (j = 0; j < s->n; j++) { + if (s->xc[j] == i) { + g = (sal_uInt16) s->xg[j]; + } + } + p[i] = (sal_uInt8) g; + } + *length = 262; + return ptr; +} + +static sal_uInt8 *PackCmapType6(CmapSubTable *s, sal_uInt32 *length) +{ + sal_uInt8* ptr = (sal_uInt8*)smalloc(s->n*2 + 10); + sal_uInt8 *p = ptr + 10; + sal_uInt32 i, j; + sal_uInt16 g; + + PutUInt16(6, ptr, 0, 1); + PutUInt16((sal_uInt16)(s->n*2+10), ptr, 2, 1); + PutUInt16(0, ptr, 4, 1); + PutUInt16(0, ptr, 6, 1); + PutUInt16((sal_uInt16)(s->n), ptr, 8, 1 ); + + for (i = 0; i < s->n; i++) { + g = 0; + for (j = 0; j < s->n; j++) { + if (s->xc[j] == i) { + g = (sal_uInt16) s->xg[j]; + } + } + PutUInt16( g, p, 2*i, 1 ); + } + *length = s->n*2+10; + return ptr; +} + + + +/* XXX it only handles Format 0 encoding tables */ +static sal_uInt8 *PackCmap(CmapSubTable *s, sal_uInt32 *length) +{ + if( s->xg[s->n-1] > 0xff ) + return PackCmapType6(s, length); + else + return PackCmapType0(s, length); +} + +static int GetRawData_cmap(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) +{ + table_cmap *t; + sal_uInt32 i; + sal_uInt32 tlen = 0; + sal_uInt32 l; + sal_uInt32 cmapsize; + sal_uInt8 *cmap; + sal_uInt32 coffset; + + assert(_this != 0); + t = (table_cmap *) _this->data; + assert(t != 0); + assert(t->n != 0); + + sal_uInt8** subtables = (sal_uInt8**)scalloc(t->n, sizeof(sal_uInt8 *)); + sal_uInt32* sizes = (sal_uInt32*)scalloc(t->n, sizeof(sal_uInt32)); + + for (i = 0; i < t->n; i++) { + subtables[i] = PackCmap(t->s+i, &l); + sizes[i] = l; + tlen += l; + } + + cmapsize = tlen + 4 + 8 * t->n; + _this->rawdata = cmap = ttmalloc(cmapsize); + + PutUInt16(0, cmap, 0, 1); + PutUInt16((sal_uInt16)t->n, cmap, 2, 1); + coffset = 4 + t->n * 8; + + for (i = 0; i < t->n; i++) { + PutUInt16((sal_uInt16)(t->s[i].id >> 16), cmap + 4, i * 8, 1); + PutUInt16((sal_uInt16)(t->s[i].id & 0xFF), cmap + 4, 2 + i * 8, 1); + PutUInt32(coffset, cmap + 4, 4 + i * 8, 1); + memcpy(cmap + coffset, subtables[i], sizes[i]); + free(subtables[i]); + coffset += sizes[i]; + } + + free(subtables); + free(sizes); + + *ptr = cmap; + *len = cmapsize; + *tag = T_cmap; + + return TTCR_OK; +} + + +static int GetRawData_name(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) +{ + list l; + sal_Int16 i=0, n; /* number of Name Records */ + int stringLen = 0; + sal_uInt8 *p1, *p2; + + *ptr = 0; + *len = 0; + *tag = 0; + + assert(_this != 0); + l = (list) _this->data; + assert(l != 0); + + if ((n = (sal_Int16)listCount(l)) == 0) return TTCR_NONAMES; + + NameRecord* nr = (NameRecord*)scalloc(n, sizeof(NameRecord)); + + listToFirst(l); + + do { + memcpy(nr+i, listCurrent(l), sizeof(NameRecord)); + stringLen += nr[i].slen; + i++; + } while (listNext(l)); + + if (stringLen > 65535) { + free(nr); + return TTCR_NAMETOOLONG; + } + + qsort(nr, n, sizeof(NameRecord), NameRecordCompareF); + + int nameLen = stringLen + 12 * n + 6; + sal_uInt8* name = (sal_uInt8*)ttmalloc(nameLen); + + PutUInt16(0, name, 0, 1); + PutUInt16(n, name, 2, 1); + PutUInt16((sal_uInt16)(6 + 12 * n), name, 4, 1); + + p1 = name + 6; + p2 = p1 + 12 * n; + + for (i = 0; i < n; i++) { + PutUInt16(nr[i].platformID, p1, 0, 1); + PutUInt16(nr[i].encodingID, p1, 2, 1); + PutUInt16(nr[i].languageID, p1, 4, 1); + PutUInt16(nr[i].nameID, p1, 6, 1); + PutUInt16(nr[i].slen, p1, 8, 1); + PutUInt16((sal_uInt16)(p2 - (name + 6 + 12 * n)), p1, 10, 1); + memcpy(p2, nr[i].sptr, nr[i].slen); + /* {int j; for(j=0; j<nr[i].slen; j++) printf("%c", nr[i].sptr[j]); printf("\n"); }; */ + p2 += nr[i].slen; + p1 += 12; + } + + free(nr); + _this->rawdata = name; + + *ptr = name; + *len = (sal_uInt16)nameLen; + *tag = T_name; + + /*{int j; for(j=0; j<nameLen; j++) printf("%c", name[j]); }; */ + + return TTCR_OK; +} + +static int GetRawData_post(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) +{ + tdata_post *p = (tdata_post *) _this->data; + sal_uInt8 *post = 0; + sal_uInt32 postLen = 0; + int ret; + + if (_this->rawdata) free(_this->rawdata); + + if (p->format == 0x00030000) { + postLen = 32; + post = ttmalloc(postLen); + PutUInt32(0x00030000, post, 0, 1); + PutUInt32(p->italicAngle, post, 4, 1); + PutUInt16(p->underlinePosition, post, 8, 1); + PutUInt16(p->underlineThickness, post, 10, 1); + PutUInt16((sal_uInt16)p->isFixedPitch, post, 12, 1); + ret = TTCR_OK; + } else { + fprintf(stderr, "Unrecognized format of a post table: %08X.\n", (int)p->format); + ret = TTCR_POSTFORMAT; + } + + *ptr = _this->rawdata = post; + *len = postLen; + *tag = T_post; + + return ret; +} + + + + + +static struct { + sal_uInt32 tag; + int (*f)(TrueTypeTable *, sal_uInt8 **, sal_uInt32 *, sal_uInt32 *); +} vtable2[] = +{ + {0, GetRawData_generic}, + {T_head, GetRawData_head}, + {T_hhea, GetRawData_hhea}, + {T_loca, GetRawData_loca}, + {T_maxp, GetRawData_maxp}, + {T_glyf, GetRawData_glyf}, + {T_cmap, GetRawData_cmap}, + {T_name, GetRawData_name}, + {T_post, GetRawData_post} + + +}; + +/* + * TrueTypeTable public methods + */ + +/* Note: Type42 fonts only need these tables: + * head, hhea, loca, maxp, cvt, prep, glyf, hmtx, fpgm + * + * Microsoft required tables + * cmap, glyf, head, hhea, hmtx, loca, maxp, name, post, OS/2 + * + * Apple required tables + * cmap, glyf, head, hhea, hmtx, loca, maxp, name, post + * + */ + +TrueTypeTable *TrueTypeTableNew(sal_uInt32 tag, + sal_uInt32 nbytes, + sal_uInt8 *ptr) +{ + TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable)); + tdata_generic* pdata = (tdata_generic*)smalloc(sizeof(tdata_generic)); + pdata->nbytes = nbytes; + pdata->tag = tag; + if (nbytes) { + pdata->ptr = ttmalloc(nbytes); + memcpy(pdata->ptr, ptr, nbytes); + } else { + pdata->ptr = 0; + } + + table->tag = 0; + table->data = pdata; + table->rawdata = 0; + + return table; +} + +TrueTypeTable *TrueTypeTableNew_head(sal_uInt32 fontRevision, + sal_uInt16 flags, + sal_uInt16 unitsPerEm, + sal_uInt8 *created, + sal_uInt16 macStyle, + sal_uInt16 lowestRecPPEM, + sal_Int16 fontDirectionHint) +{ + assert(created != 0); + + TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable)); + sal_uInt8* ptr = (sal_uInt8*)ttmalloc(TABLESIZE_head); + + + PutUInt32(0x00010000, ptr, 0, 1); /* version */ + PutUInt32(fontRevision, ptr, 4, 1); + PutUInt32(0x5F0F3CF5, ptr, 12, 1); /* magic number */ + PutUInt16(flags, ptr, 16, 1); + PutUInt16(unitsPerEm, ptr, 18, 1); + memcpy(ptr+20, created, 8); /* Created Long Date */ + memset(ptr+28, 0, 8); /* Modified Long Date */ + PutUInt16(macStyle, ptr, 44, 1); + PutUInt16(lowestRecPPEM, ptr, 46, 1); + PutUInt16(fontDirectionHint, ptr, 48, 1); + PutUInt16(0, ptr, 52, 1); /* glyph data format: 0 */ + + table->data = (void *) ptr; + table->tag = T_head; + table->rawdata = 0; + + return table; +} + +TrueTypeTable *TrueTypeTableNew_hhea(sal_Int16 ascender, + sal_Int16 descender, + sal_Int16 linegap, + sal_Int16 caretSlopeRise, + sal_Int16 caretSlopeRun) +{ + TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable)); + sal_uInt8* ptr = (sal_uInt8*)ttmalloc(TABLESIZE_hhea); + + PutUInt32(0x00010000, ptr, 0, 1); /* version */ + PutUInt16(ascender, ptr, 4, 1); + PutUInt16(descender, ptr, 6, 1); + PutUInt16(linegap, ptr, 8, 1); + PutUInt16(caretSlopeRise, ptr, 18, 1); + PutUInt16(caretSlopeRun, ptr, 20, 1); + PutUInt16(0, ptr, 22, 1); /* reserved 1 */ + PutUInt16(0, ptr, 24, 1); /* reserved 2 */ + PutUInt16(0, ptr, 26, 1); /* reserved 3 */ + PutUInt16(0, ptr, 28, 1); /* reserved 4 */ + PutUInt16(0, ptr, 30, 1); /* reserved 5 */ + PutUInt16(0, ptr, 32, 1); /* metricDataFormat */ + + table->data = (void *) ptr; + table->tag = T_hhea; + table->rawdata = 0; + + return table; +} + +TrueTypeTable *TrueTypeTableNew_loca(void) +{ + TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable)); + table->data = smalloc(sizeof(tdata_loca)); + + ((tdata_loca *)table->data)->nbytes = 0; + ((tdata_loca *)table->data)->ptr = 0; + + table->tag = T_loca; + table->rawdata = 0; + + return table; +} + +TrueTypeTable *TrueTypeTableNew_maxp(sal_uInt8 *maxp, int size) +{ + TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable)); + table->data = ttmalloc(TABLESIZE_maxp); + + if (maxp && size == TABLESIZE_maxp) { + memcpy(table->data, maxp, TABLESIZE_maxp); + } + + table->tag = T_maxp; + table->rawdata = 0; + + return table; +} + +TrueTypeTable *TrueTypeTableNew_glyf(void) +{ + TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable)); + list l = listNewEmpty(); + + assert(l != 0); + + listSetElementDtor(l, (list_destructor)FreeGlyphData); + + table->data = l; + table->rawdata = 0; + table->tag = T_glyf; + + return table; +} + +TrueTypeTable *TrueTypeTableNew_cmap(void) +{ + TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable)); + table_cmap* cmap = (table_cmap*)smalloc(sizeof(table_cmap)); + + cmap->n = 0; + cmap->m = CMAP_SUBTABLE_INIT; + cmap->s = (CmapSubTable *) scalloc(CMAP_SUBTABLE_INIT, sizeof(CmapSubTable)); + memset(cmap->s, 0, sizeof(CmapSubTable) * CMAP_SUBTABLE_INIT); + + table->data = (table_cmap *) cmap; + + table->rawdata = 0; + table->tag = T_cmap; + + return table; +} + +static void DisposeNameRecord(void *ptr) +{ + if (ptr != 0) { + NameRecord *nr = (NameRecord *) ptr; + if (nr->sptr) free(nr->sptr); + free(ptr); + } +} + +static NameRecord* NameRecordNewCopy(NameRecord *nr) +{ + NameRecord* p = (NameRecord*)smalloc(sizeof(NameRecord)); + + memcpy(p, nr, sizeof(NameRecord)); + + if (p->slen) { + p->sptr = (sal_uInt8*)smalloc(p->slen); + memcpy(p->sptr, nr->sptr, p->slen); + } + + return p; +} + +TrueTypeTable *TrueTypeTableNew_name(int n, NameRecord *nr) +{ + TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable)); + list l = listNewEmpty(); + + assert(l != 0); + + listSetElementDtor(l, (list_destructor)DisposeNameRecord); + + if (n != 0) { + int i; + for (i = 0; i < n; i++) { + listAppend(l, NameRecordNewCopy(nr+i)); + } + } + + table->data = l; + table->rawdata = 0; + table->tag = T_name; + + return table; +} + +TrueTypeTable *TrueTypeTableNew_post(sal_uInt32 format, + sal_uInt32 italicAngle, + sal_Int16 underlinePosition, + sal_Int16 underlineThickness, + sal_uInt32 isFixedPitch) +{ + assert(format == 0x00030000); /* Only format 3.0 is supported at this time */ + TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable)); + tdata_post* post = (tdata_post*)smalloc(sizeof(tdata_post)); + + post->format = format; + post->italicAngle = italicAngle; + post->underlinePosition = underlinePosition; + post->underlineThickness = underlineThickness; + post->isFixedPitch = isFixedPitch; + post->ptr = 0; + + table->data = post; + table->rawdata = 0; + table->tag = T_post; + + return table; +} + +int GetRawData(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag) +{ + /* XXX do a binary search */ + unsigned int i; + + assert(_this != 0); + assert(ptr != 0); + assert(len != 0); + assert(tag != 0); + + *ptr = 0; *len = 0; *tag = 0; + + if (_this->rawdata) { + free(_this->rawdata); + _this->rawdata = 0; + } + + for(i=0; i < sizeof(vtable2)/sizeof(*vtable2); i++) { + if (_this->tag == vtable2[i].tag) { + return vtable2[i].f(_this, ptr, len, tag); + } + } + + assert(!"Unknwon TrueType table.\n"); + return TTCR_UNKNOWN; +} + +void cmapAdd(TrueTypeTable *table, sal_uInt32 id, sal_uInt32 c, sal_uInt32 g) +{ + sal_uInt32 i, found; + table_cmap *t; + CmapSubTable *s; + + assert(table != 0); + assert(table->tag == T_cmap); + t = (table_cmap *) table->data; assert(t != 0); + s = t->s; assert(s != 0); + + found = 0; + + for (i = 0; i < t->n; i++) { + if (s[i].id == id) { + found = 1; + break; + } + } + + if (!found) { + if (t->n == t->m) { + CmapSubTable* tmp = (CmapSubTable*)scalloc(t->m + CMAP_SUBTABLE_INCR, sizeof(CmapSubTable)); + memset(tmp, 0, t->m + CMAP_SUBTABLE_INCR * sizeof(CmapSubTable)); + memcpy(tmp, s, sizeof(CmapSubTable) * t->m); + t->m += CMAP_SUBTABLE_INCR; + free(s); + s = tmp; + t->s = s; + } + + for (i = 0; i < t->n; i++) { + if (s[i].id > id) break; + } + + if (i < t->n) { + memmove(s+i+1, s+i, t->n-i); + } + + t->n++; + + s[i].id = id; + s[i].n = 0; + s[i].m = CMAP_PAIR_INIT; + s[i].xc = (sal_uInt32*)scalloc(CMAP_PAIR_INIT, sizeof(sal_uInt32)); + s[i].xg = (sal_uInt32*)scalloc(CMAP_PAIR_INIT, sizeof(sal_uInt32)); + } + + if (s[i].n == s[i].m) { + sal_uInt32* tmp1 = (sal_uInt32*)scalloc(s[i].m + CMAP_PAIR_INCR, sizeof(sal_uInt32)); + sal_uInt32* tmp2 = (sal_uInt32*)scalloc(s[i].m + CMAP_PAIR_INCR, sizeof(sal_uInt32)); + assert(tmp1 != 0); + assert(tmp2 != 0); + memcpy(tmp1, s[i].xc, sizeof(sal_uInt32) * s[i].m); + memcpy(tmp2, s[i].xg, sizeof(sal_uInt32) * s[i].m); + s[i].m += CMAP_PAIR_INCR; + free(s[i].xc); + free(s[i].xg); + s[i].xc = tmp1; + s[i].xg = tmp2; + } + + s[i].xc[s[i].n] = c; + s[i].xg[s[i].n] = g; + s[i].n++; +} + +sal_uInt32 glyfAdd(TrueTypeTable *table, GlyphData *glyphdata, TrueTypeFont *fnt) +{ + list l; + sal_uInt32 currentID; + int ret, n, ncomponents; + GlyphData *gd; + + assert(table != 0); + assert(table->tag == T_glyf); + + if (!glyphdata) return (sal_uInt32)~0; + + std::vector< sal_uInt32 > glyphlist; + + ncomponents = GetTTGlyphComponents(fnt, glyphdata->glyphID, glyphlist); + + l = (list) table->data; + if (listCount(l) > 0) { + listToLast(l); + ret = n = ((GlyphData *) listCurrent(l))->newID + 1; + } else { + ret = n = 0; + } + glyphdata->newID = n++; + listAppend(l, glyphdata); + + if (ncomponents > 1 && glyphlist.size() > 1 ) + { + std::vector< sal_uInt32 >::const_iterator it = glyphlist.begin(); + ++it; + /* glyphData->glyphID is always the first glyph on the list */ + do + { + int found = 0; + currentID = *it; + /* XXX expensive! should be rewritten with sorted arrays! */ + listToFirst(l); + do { + if (((GlyphData *) listCurrent(l))->glyphID == currentID) { + found = 1; + break; + } + } while (listNext(l)); + + if (!found) { + gd = GetTTRawGlyphData(fnt, currentID); + gd->newID = n++; + listAppend(l, gd); + } + } while( ++it != glyphlist.end() ); + } + + return ret; +} + +sal_uInt32 glyfCount(const TrueTypeTable *table) +{ + assert(table != 0); + assert(table->tag == T_glyf); + return listCount((list) table->data); +} + + +void nameAdd(TrueTypeTable *table, NameRecord *nr) +{ + list l; + + assert(table != 0); + assert(table->tag == T_name); + + l = (list) table->data; + + listAppend(l, NameRecordNewCopy(nr)); +} + +static TrueTypeTable *FindTable(TrueTypeCreator *tt, sal_uInt32 tag) +{ + if (listIsEmpty(tt->tables)) return 0; + + listToFirst(tt->tables); + + do { + if (((TrueTypeTable *) listCurrent(tt->tables))->tag == tag) { + return (TrueTypeTable*)listCurrent(tt->tables); + } + } while (listNext(tt->tables)); + + return 0; +} + +/* This function processes all the tables and synchronizes them before creating + * the output TrueType stream. + * + * *** It adds two TrueType tables to the font: 'loca' and 'hmtx' *** + * + * It does: + * + * - Re-numbers glyph IDs and creates 'glyf', 'loca', and 'hmtx' tables. + * - Calculates xMin, yMin, xMax, and yMax and stores values in 'head' table. + * - Stores indexToLocFormat in 'head' + * - updates 'maxp' table + * - Calculates advanceWidthMax, minLSB, minRSB, xMaxExtent and numberOfHMetrics + * in 'hhea' table + * + */ +static void ProcessTables(TrueTypeCreator *tt) +{ + TrueTypeTable *glyf, *loca, *head, *maxp, *hhea; + list glyphlist; + sal_uInt32 nGlyphs, locaLen = 0, glyfLen = 0; + sal_Int16 xMin = 0, yMin = 0, xMax = 0, yMax = 0; + sal_uInt32 i = 0; + sal_Int16 indexToLocFormat; + sal_uInt8 *hmtxPtr, *hheaPtr; + sal_uInt32 hmtxSize; + sal_uInt8 *p1, *p2; + sal_uInt16 maxPoints = 0, maxContours = 0, maxCompositePoints = 0, maxCompositeContours = 0; + int nlsb = 0; + sal_uInt32 *gid; /* array of old glyphIDs */ + + glyf = FindTable(tt, T_glyf); + glyphlist = (list) glyf->data; + nGlyphs = listCount(glyphlist); + assert(nGlyphs != 0); + gid = (sal_uInt32*)scalloc(nGlyphs, sizeof(sal_uInt32)); + + RemoveTable(tt, T_loca); + RemoveTable(tt, T_hmtx); + + /* XXX Need to make sure that composite glyphs do not break during glyph renumbering */ + + listToFirst(glyphlist); + do { + GlyphData *gd = (GlyphData *) listCurrent(glyphlist); + sal_Int16 z; + glyfLen += gd->nbytes; + /* XXX if (gd->nbytes & 1) glyfLen++; */ + + + assert(gd->newID == i); + gid[i++] = gd->glyphID; + /* gd->glyphID = i++; */ + + /* printf("IDs: %d %d.\n", gd->glyphID, gd->newID); */ + + if (gd->nbytes != 0) { + z = GetInt16(gd->ptr, 2, 1); + if (z < xMin) xMin = z; + + z = GetInt16(gd->ptr, 4, 1); + if (z < yMin) yMin = z; + + z = GetInt16(gd->ptr, 6, 1); + if (z > xMax) xMax = z; + + z = GetInt16(gd->ptr, 8, 1); + if (z > yMax) yMax = z; + } + + if (gd->compflag == 0) { /* non-composite glyph */ + if (gd->npoints > maxPoints) maxPoints = gd->npoints; + if (gd->ncontours > maxContours) maxContours = gd->ncontours; + } else { /* composite glyph */ + if (gd->npoints > maxCompositePoints) maxCompositePoints = gd->npoints; + if (gd->ncontours > maxCompositeContours) maxCompositeContours = gd->ncontours; + } + + } while (listNext(glyphlist)); + + indexToLocFormat = (glyfLen / 2 > 0xFFFF) ? 1 : 0; + locaLen = indexToLocFormat ? (nGlyphs + 1) << 2 : (nGlyphs + 1) << 1; + + sal_uInt8* glyfPtr = ttmalloc(glyfLen); + sal_uInt8* locaPtr = ttmalloc(locaLen); + TTSimpleGlyphMetrics* met = (TTSimpleGlyphMetrics*)scalloc(nGlyphs, sizeof(TTSimpleGlyphMetrics)); + i = 0; + + listToFirst(glyphlist); + p1 = glyfPtr; + p2 = locaPtr; + do { + GlyphData *gd = (GlyphData *) listCurrent(glyphlist); + + if (gd->compflag) { /* re-number all components */ + sal_uInt16 flags, index; + sal_uInt8 *ptr = gd->ptr + 10; + do { + sal_uInt32 j; + flags = GetUInt16(ptr, 0, 1); + index = GetUInt16(ptr, 2, 1); + /* XXX use the sorted array of old to new glyphID mapping and do a binary search */ + for (j = 0; j < nGlyphs; j++) { + if (gid[j] == index) { + break; + } + } + /* printf("X: %d -> %d.\n", index, j); */ + + PutUInt16((sal_uInt16) j, ptr, 2, 1); + + ptr += 4; + + if (flags & ARG_1_AND_2_ARE_WORDS) { + ptr += 4; + } else { + ptr += 2; + } + + if (flags & WE_HAVE_A_SCALE) { + ptr += 2; + } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) { + ptr += 4; + } else if (flags & WE_HAVE_A_TWO_BY_TWO) { + ptr += 8; + } + } while (flags & MORE_COMPONENTS); + } + + if (gd->nbytes != 0) { + memcpy(p1, gd->ptr, gd->nbytes); + } + if (indexToLocFormat == 1) { + PutUInt32(p1 - glyfPtr, p2, 0, 1); + p2 += 4; + } else { + PutUInt16((sal_uInt16)((p1 - glyfPtr) >> 1), p2, 0, 1); + p2 += 2; + } + p1 += gd->nbytes; + + /* fill the array of metrics */ + met[i].adv = gd->aw; + met[i].sb = gd->lsb; + i++; + } while (listNext(glyphlist)); + + free(gid); + + if (indexToLocFormat == 1) { + PutUInt32(p1 - glyfPtr, p2, 0, 1); + } else { + PutUInt16((sal_uInt16)((p1 - glyfPtr) >> 1), p2, 0, 1); + } + + glyf->rawdata = glyfPtr; + + loca = TrueTypeTableNew_loca(); assert(loca != 0); + ((tdata_loca *) loca->data)->ptr = locaPtr; + ((tdata_loca *) loca->data)->nbytes = locaLen; + + AddTable(tt, loca); + + head = FindTable(tt, T_head); + sal_uInt8* const pHeadData = (sal_uInt8*)head->data; + PutInt16(xMin, pHeadData, 36, 1); + PutInt16(yMin, pHeadData, 38, 1); + PutInt16(xMax, pHeadData, 40, 1); + PutInt16(yMax, pHeadData, 42, 1); + PutInt16(indexToLocFormat, pHeadData, 50, 1); + + maxp = FindTable(tt, T_maxp); + + sal_uInt8* const pMaxpData = (sal_uInt8*)maxp->data; + PutUInt16((sal_uInt16)nGlyphs, pMaxpData, 4, 1); + PutUInt16(maxPoints, pMaxpData, 6, 1); + PutUInt16(maxContours, pMaxpData, 8, 1); + PutUInt16(maxCompositePoints, pMaxpData, 10, 1); + PutUInt16(maxCompositeContours, pMaxpData, 12, 1); + +#if 0 + /* XXX do not overwrite the existing data. Fix: re-calculate these numbers here */ + PutUInt16(2, maxp->data, 14, 1); /* maxZones is always 2 */ + PutUInt16(0, maxp->data, 16, 1); /* maxTwilightPoints */ + PutUInt16(0, maxp->data, 18, 1); /* maxStorage */ + PutUInt16(0, maxp->data, 20, 1); /* maxFunctionDefs */ + PutUint16(0, maxp->data, 22, 1); /* maxInstructionDefs */ + PutUint16(0, maxp->data, 24, 1); /* maxStackElements */ + PutUint16(0, maxp->data, 26, 1); /* maxSizeOfInstructions */ + PutUint16(0, maxp->data, 28, 1); /* maxComponentElements */ + PutUint16(0, maxp->data, 30, 1); /* maxComponentDepth */ +#endif + + /* + * Generate an htmx table and update hhea table + */ + hhea = FindTable(tt, T_hhea); assert(hhea != 0); + hheaPtr = (sal_uInt8 *) hhea->data; + if (nGlyphs > 2) { + for (i = nGlyphs - 1; i > 0; i--) { + if (met[i].adv != met[i-1].adv) break; + } + nlsb = nGlyphs - 1 - i; + } + hmtxSize = (nGlyphs - nlsb) * 4 + nlsb * 2; + hmtxPtr = ttmalloc(hmtxSize); + p1 = hmtxPtr; + + for (i = 0; i < nGlyphs; i++) { + if (i < nGlyphs - nlsb) { + PutUInt16(met[i].adv, p1, 0, 1); + PutUInt16(met[i].sb, p1, 2, 1); + p1 += 4; + } else { + PutUInt16(met[i].sb, p1, 0, 1); + p1 += 2; + } + } + + AddTable(tt, TrueTypeTableNew(T_hmtx, hmtxSize, hmtxPtr)); + PutUInt16((sal_uInt16)(nGlyphs - nlsb), hheaPtr, 34, 1); + free(hmtxPtr); + free(met); +} + +} // namespace vcl + +extern "C" +{ + /** + * TrueTypeCreator destructor. It calls destructors for all TrueTypeTables added to it. + */ + void TrueTypeCreatorDispose(vcl::TrueTypeCreator *_this) + { + listDispose(_this->tables); + free(_this); + } + + + /** + * Destructor for the TrueTypeTable object. + */ + void TrueTypeTableDispose(vcl::TrueTypeTable *_this) + { + /* XXX do a binary search */ + unsigned int i; + + assert(_this != 0); + + if (_this->rawdata) free(_this->rawdata); + + for(i=0; i < sizeof(vcl::vtable1)/sizeof(*vcl::vtable1); i++) { + if (_this->tag == vcl::vtable1[i].tag) { + vcl::vtable1[i].f(_this); + return; + } + } + assert(!"Unknown TrueType table.\n"); + } +} + + +#ifdef TEST_TTCR +int main(void) +{ + TrueTypeCreator *ttcr; + sal_uInt8 *t1, *t2, *t3, *t4, *t5, *t6, *t7; + + TrueTypeCreatorNewEmpty(mkTag('t','r','u','e'), &ttcr); + + t1 = malloc(1000); memset(t1, 'a', 1000); + t2 = malloc(2000); memset(t2, 'b', 2000); + t3 = malloc(3000); memset(t3, 'c', 3000); + t4 = malloc(4000); memset(t4, 'd', 4000); + t5 = malloc(5000); memset(t5, 'e', 5000); + t6 = malloc(6000); memset(t6, 'f', 6000); + t7 = malloc(7000); memset(t7, 'g', 7000); + + AddTable(ttcr, TrueTypeTableNew(0x6D617870, 1000, t1)); + AddTable(ttcr, TrueTypeTableNew(0x4F532F32, 2000, t2)); + AddTable(ttcr, TrueTypeTableNew(0x636D6170, 3000, t3)); + AddTable(ttcr, TrueTypeTableNew(0x6C6F6361, 4000, t4)); + AddTable(ttcr, TrueTypeTableNew(0x68686561, 5000, t5)); + AddTable(ttcr, TrueTypeTableNew(0x676C7966, 6000, t6)); + AddTable(ttcr, TrueTypeTableNew(0x6B65726E, 7000, t7)); + + free(t1); + free(t2); + free(t3); + free(t4); + free(t5); + free(t6); + free(t7); + + + StreamToFile(ttcr, "ttcrout.ttf"); + + TrueTypeCreatorDispose(ttcr); + return 0; +} +#endif diff --git a/vcl/source/fontsubset/ttcr.h b/vcl/source/fontsubset/ttcr.h deleted file mode 100644 index 95aa1a6c9e99..000000000000 --- a/vcl/source/fontsubset/ttcr.h +++ /dev/null @@ -1,280 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: ttcr.h,v $ - * $Revision: 1.4 $ - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -/* $Id: ttcr.h,v 1.4 2008-04-11 10:17:09 rt Exp $ */ - -/** - * - * @file ttcr.h - * @brief TrueType font creator - * @author Alexander Gelfenbain - */ - -#ifndef __TTCR_H -#define __TTCR_H - -#include "sft.h" -#include "list.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - - typedef struct _TrueTypeCreator TrueTypeCreator; - -/* TrueType data types */ - typedef struct { - sal_uInt16 aw; - sal_Int16 lsb; - } longHorMetrics; - -/* A generic base class for all TrueType tables */ - typedef struct { - sal_uInt32 tag; /* table tag */ - sal_uInt8 *rawdata; /* raw data allocated by GetRawData_*() */ - void *data; /* table specific data */ - } TrueTypeTable; - -/** Error codes for most functions */ - enum TTCRErrCodes { - TTCR_OK = 0, /**< no error */ - TTCR_ZEROGLYPHS = 1, /**< At least one glyph should be defined */ - TTCR_UNKNOWN = 2, /**< Unknown TrueType table */ - TTCR_GLYPHSEQ = 3, /**< Glyph IDs are not sequential in the glyf table */ - TTCR_NONAMES = 4, /**< 'name' table does not contain any names */ - TTCR_NAMETOOLONG = 5, /**< 'name' table is too long (string data > 64K) */ - TTCR_POSTFORMAT = 6 /**< unsupported format of a 'post' table */ - }; - -/* ============================================================================ - * - * TrueTypeCreator methods - * - * ============================================================================ */ - -/** - * TrueTypeCreator constructor. - * Allocates all internal structures. - */ - void TrueTypeCreatorNewEmpty(sal_uInt32 tag, TrueTypeCreator **_this); - -/** - * TrueTypeCreator destructor. It calls destructors for all TrueTypeTables added to it. - */ - void TrueTypeCreatorDispose(TrueTypeCreator *_this); - -/** - * Adds a TrueType table to the TrueType creator. - * SF_TABLEFORMAT value. - * @return value of SFErrCodes type - */ - int AddTable(TrueTypeCreator *_this, TrueTypeTable *table); - -/** - * Removes a TrueType table from the TrueType creator if it is stored there. - * It also calls a TrueTypeTable destructor. - * Note: all generic tables (with tag 0) will be removed if this function is - * called with the second argument of 0. - * @return value of SFErrCodes type - */ - void RemoveTable(TrueTypeCreator *_this, sal_uInt32 tag); - - - -/** - * Writes a TrueType font generated by the TrueTypeCreator to a segment of - * memory that this method allocates. When it is not needed anymore the caller - * is supposed to call free() on it. - * @return value of SFErrCodes type - */ - int StreamToMemory(TrueTypeCreator *_this, sal_uInt8 **ptr, sal_uInt32 *length); - -/** - * Writes a TrueType font generated by the TrueTypeCreator to a file - * @return value of SFErrCodes type - */ - int StreamToFile(TrueTypeCreator *_this, const char* fname); - - -/* ============================================================================ - * - * TrueTypeTable methods - * - * ============================================================================ */ - -/** - * Destructor for the TrueTypeTable object. - */ - void TrueTypeTableDispose(TrueTypeTable *); - -/** - * This function converts the data of a TrueType table to a raw array of bytes. - * It may allocates the memory for it and returns the size of the raw data in bytes. - * If memory is allocated it does not need to be freed by the caller of this function, - * since the pointer to it is stored in the TrueTypeTable and it is freed by the destructor - * @return TTCRErrCode - * - */ - - int GetRawData(TrueTypeTable *, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag); - -/** - * - * Creates a new raw TrueType table. The difference between this constructor and - * TrueTypeTableNew_tag constructors is that the latter create structured tables - * while this constructor just copies memory pointed to by ptr to its buffer - * and stores its length. This constructor is suitable for data that is not - * supposed to be processed in any way, just written to the resulting TTF file. - */ - TrueTypeTable *TrueTypeTableNew(sal_uInt32 tag, - sal_uInt32 nbytes, - sal_uInt8 *ptr); - -/** - * Creates a new 'head' table for a TrueType font. - * Allocates memory for it. Since a lot of values in the 'head' table depend on the - * rest of the tables in the TrueType font this table should be the last one added - * to the font. - */ - TrueTypeTable *TrueTypeTableNew_head(sal_uInt32 fontRevision, - sal_uInt16 flags, - sal_uInt16 unitsPerEm, - sal_uInt8 *created, - sal_uInt16 macStyle, - sal_uInt16 lowestRecPPEM, - sal_Int16 fontDirectionHint); - -/** - * Creates a new 'hhea' table for a TrueType font. - * Allocates memory for it and stores it in the hhea pointer. - */ - TrueTypeTable *TrueTypeTableNew_hhea(sal_Int16 ascender, - sal_Int16 descender, - sal_Int16 linegap, - sal_Int16 caretSlopeRise, - sal_Int16 caretSlopeRun); - -/** - * Creates a new empty 'loca' table for a TrueType font. - * - * INTERNAL: gets called only from ProcessTables(); - */ - TrueTypeTable *TrueTypeTableNew_loca(void); - -/** - * Creates a new 'maxp' table based on an existing maxp table. - * If maxp is 0, a new empty maxp table is created - * size specifies the size of existing maxp table for - * error-checking purposes - */ - TrueTypeTable *TrueTypeTableNew_maxp(sal_uInt8 *maxp, int size); - -/** - * Creates a new empty 'glyf' table. - */ - TrueTypeTable *TrueTypeTableNew_glyf(void); - -/** - * Creates a new empty 'cmap' table. - */ - TrueTypeTable *TrueTypeTableNew_cmap(void); - -/** - * Creates a new 'name' table. If n != 0 the table gets populated by - * the Name Records stored in the nr array. This function allocates - * memory for its own copy of NameRecords, so nr array has to - * be explicitly deallocated when it is not needed. - */ - TrueTypeTable *TrueTypeTableNew_name(int n, NameRecord *nr); - -/** - * Creates a new 'post' table of one of the supported formats - */ - TrueTypeTable *TrueTypeTableNew_post(sal_uInt32 format, - sal_uInt32 italicAngle, - sal_Int16 underlinePosition, - sal_Int16 underlineThickness, - sal_uInt32 isFixedPitch); - - -/*------------------------------------------------------------------------------ - * - * Table manipulation functions - * - *------------------------------------------------------------------------------*/ - - -/** - * Add a character/glyph pair to a cmap table - */ - void cmapAdd(TrueTypeTable *, sal_uInt32 id, sal_uInt32 c, sal_uInt32 g); - -/** - * Add a glyph to a glyf table. - * - * @return glyphID of the glyph in the new font - * - * NOTE: This function does not duplicate GlyphData, so memory will be - * deallocated in the table destructor - */ - sal_uInt32 glyfAdd(TrueTypeTable *, GlyphData *glyphdata, TrueTypeFont *fnt); - -/** - * Query the number of glyphs currently stored in the 'glyf' table - * - */ - sal_uInt32 glyfCount(const TrueTypeTable *); - -/** - * Add a Name Record to a name table. - * NOTE: This function duplicates NameRecord, so the argument - * has to be deallocated by the caller (unlike glyfAdd) - */ - void nameAdd(TrueTypeTable *, NameRecord *nr); - - - -/* - * Private Data Types - */ - - struct _TrueTypeCreator { - sal_uInt32 tag; /**< TrueType file tag */ - list tables; /**< List of table tags and pointers */ - }; - - - -#ifdef __cplusplus -} -#endif - -#endif /* __TTCR_H */ diff --git a/vcl/source/fontsubset/ttcr.hxx b/vcl/source/fontsubset/ttcr.hxx new file mode 100644 index 000000000000..5b47f09d552a --- /dev/null +++ b/vcl/source/fontsubset/ttcr.hxx @@ -0,0 +1,261 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +/** + * + * @file ttcr.h + * @brief TrueType font creator + * @author Alexander Gelfenbain + */ + +#ifndef __TTCR_H +#define __TTCR_H + +#include "sft.hxx" + +namespace vcl +{ + typedef struct _TrueTypeCreator TrueTypeCreator; + +/* TrueType data types */ + typedef struct { + sal_uInt16 aw; + sal_Int16 lsb; + } longHorMetrics; + +/* A generic base class for all TrueType tables */ + struct TrueTypeTable { + sal_uInt32 tag; /* table tag */ + sal_uInt8 *rawdata; /* raw data allocated by GetRawData_*() */ + void *data; /* table specific data */ + }; + +/** Error codes for most functions */ + enum TTCRErrCodes { + TTCR_OK = 0, /**< no error */ + TTCR_ZEROGLYPHS = 1, /**< At least one glyph should be defined */ + TTCR_UNKNOWN = 2, /**< Unknown TrueType table */ + TTCR_GLYPHSEQ = 3, /**< Glyph IDs are not sequential in the glyf table */ + TTCR_NONAMES = 4, /**< 'name' table does not contain any names */ + TTCR_NAMETOOLONG = 5, /**< 'name' table is too long (string data > 64K) */ + TTCR_POSTFORMAT = 6 /**< unsupported format of a 'post' table */ + }; + +/* ============================================================================ + * + * TrueTypeCreator methods + * + * ============================================================================ */ + +/** + * TrueTypeCreator constructor. + * Allocates all internal structures. + */ + void TrueTypeCreatorNewEmpty(sal_uInt32 tag, TrueTypeCreator **_this); + +/** + * Adds a TrueType table to the TrueType creator. + * SF_TABLEFORMAT value. + * @return value of SFErrCodes type + */ + int AddTable(TrueTypeCreator *_this, TrueTypeTable *table); + +/** + * Removes a TrueType table from the TrueType creator if it is stored there. + * It also calls a TrueTypeTable destructor. + * Note: all generic tables (with tag 0) will be removed if this function is + * called with the second argument of 0. + * @return value of SFErrCodes type + */ + void RemoveTable(TrueTypeCreator *_this, sal_uInt32 tag); + + + +/** + * Writes a TrueType font generated by the TrueTypeCreator to a segment of + * memory that this method allocates. When it is not needed anymore the caller + * is supposed to call free() on it. + * @return value of SFErrCodes type + */ + int StreamToMemory(TrueTypeCreator *_this, sal_uInt8 **ptr, sal_uInt32 *length); + +/** + * Writes a TrueType font generated by the TrueTypeCreator to a file + * @return value of SFErrCodes type + */ + int StreamToFile(TrueTypeCreator *_this, const char* fname); + + +/* ============================================================================ + * + * TrueTypeTable methods + * + * ============================================================================ */ + + +/** + * This function converts the data of a TrueType table to a raw array of bytes. + * It may allocates the memory for it and returns the size of the raw data in bytes. + * If memory is allocated it does not need to be freed by the caller of this function, + * since the pointer to it is stored in the TrueTypeTable and it is freed by the destructor + * @return TTCRErrCode + * + */ + + int GetRawData(TrueTypeTable *, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag); + +/** + * + * Creates a new raw TrueType table. The difference between this constructor and + * TrueTypeTableNew_tag constructors is that the latter create structured tables + * while this constructor just copies memory pointed to by ptr to its buffer + * and stores its length. This constructor is suitable for data that is not + * supposed to be processed in any way, just written to the resulting TTF file. + */ + TrueTypeTable *TrueTypeTableNew(sal_uInt32 tag, + sal_uInt32 nbytes, + sal_uInt8 *ptr); + +/** + * Creates a new 'head' table for a TrueType font. + * Allocates memory for it. Since a lot of values in the 'head' table depend on the + * rest of the tables in the TrueType font this table should be the last one added + * to the font. + */ + TrueTypeTable *TrueTypeTableNew_head(sal_uInt32 fontRevision, + sal_uInt16 flags, + sal_uInt16 unitsPerEm, + sal_uInt8 *created, + sal_uInt16 macStyle, + sal_uInt16 lowestRecPPEM, + sal_Int16 fontDirectionHint); + +/** + * Creates a new 'hhea' table for a TrueType font. + * Allocates memory for it and stores it in the hhea pointer. + */ + TrueTypeTable *TrueTypeTableNew_hhea(sal_Int16 ascender, + sal_Int16 descender, + sal_Int16 linegap, + sal_Int16 caretSlopeRise, + sal_Int16 caretSlopeRun); + +/** + * Creates a new empty 'loca' table for a TrueType font. + * + * INTERNAL: gets called only from ProcessTables(); + */ + TrueTypeTable *TrueTypeTableNew_loca(void); + +/** + * Creates a new 'maxp' table based on an existing maxp table. + * If maxp is 0, a new empty maxp table is created + * size specifies the size of existing maxp table for + * error-checking purposes + */ + TrueTypeTable *TrueTypeTableNew_maxp(sal_uInt8 *maxp, int size); + +/** + * Creates a new empty 'glyf' table. + */ + TrueTypeTable *TrueTypeTableNew_glyf(void); + +/** + * Creates a new empty 'cmap' table. + */ + TrueTypeTable *TrueTypeTableNew_cmap(void); + +/** + * Creates a new 'name' table. If n != 0 the table gets populated by + * the Name Records stored in the nr array. This function allocates + * memory for its own copy of NameRecords, so nr array has to + * be explicitly deallocated when it is not needed. + */ + TrueTypeTable *TrueTypeTableNew_name(int n, NameRecord *nr); + +/** + * Creates a new 'post' table of one of the supported formats + */ + TrueTypeTable *TrueTypeTableNew_post(sal_uInt32 format, + sal_uInt32 italicAngle, + sal_Int16 underlinePosition, + sal_Int16 underlineThickness, + sal_uInt32 isFixedPitch); + + +/*------------------------------------------------------------------------------ + * + * Table manipulation functions + * + *------------------------------------------------------------------------------*/ + + +/** + * Add a character/glyph pair to a cmap table + */ + void cmapAdd(TrueTypeTable *, sal_uInt32 id, sal_uInt32 c, sal_uInt32 g); + +/** + * Add a glyph to a glyf table. + * + * @return glyphID of the glyph in the new font + * + * NOTE: This function does not duplicate GlyphData, so memory will be + * deallocated in the table destructor + */ + sal_uInt32 glyfAdd(TrueTypeTable *, GlyphData *glyphdata, TrueTypeFont *fnt); + +/** + * Query the number of glyphs currently stored in the 'glyf' table + * + */ + sal_uInt32 glyfCount(const TrueTypeTable *); + +/** + * Add a Name Record to a name table. + * NOTE: This function duplicates NameRecord, so the argument + * has to be deallocated by the caller (unlike glyfAdd) + */ + void nameAdd(TrueTypeTable *, NameRecord *nr); + +} // namespace + + +extern "C" +{ +/** + * Destructor for the TrueTypeTable object. + */ + void TrueTypeTableDispose(vcl::TrueTypeTable *); + +/** + * TrueTypeCreator destructor. It calls destructors for all TrueTypeTables added to it. + */ + void TrueTypeCreatorDispose(vcl::TrueTypeCreator *_this); +} + +#endif /* __TTCR_H */ diff --git a/vcl/source/fontsubset/u2big5.inc b/vcl/source/fontsubset/u2big5.inc index 2883e9d99094..951b65cffc25 100644 --- a/vcl/source/fontsubset/u2big5.inc +++ b/vcl/source/fontsubset/u2big5.inc @@ -6,9 +6,6 @@ * * OpenOffice.org - a multi-platform office productivity suite * - * $RCSfile: u2big5.inc,v $ - * $Revision: 1.4 $ - * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify @@ -28,6 +25,8 @@ * ************************************************************************/ +// TODO: use generic RTL_TEXTENCODING_BIG5 to get rid of this file + sal_uInt16pair xlat_1_3[13798] = { {0x0020, 0x0020},{0x0021, 0x0021},{0x0022, 0x0022},{0x0023, 0x0023},{0x0024, 0x0024},{0x0025, 0x0025},{0x0026, 0x0026},{0x0027, 0x0027}, {0x0028, 0x0028},{0x0029, 0x0029},{0x002A, 0x002A},{0x002B, 0x002B},{0x002C, 0x002C},{0x002D, 0x002D},{0x002E, 0x002E},{0x002F, 0x002F}, diff --git a/vcl/source/fontsubset/u2johab.inc b/vcl/source/fontsubset/u2johab.inc index ae07cc571fb8..f7a75afaf503 100644 --- a/vcl/source/fontsubset/u2johab.inc +++ b/vcl/source/fontsubset/u2johab.inc @@ -6,9 +6,6 @@ * * OpenOffice.org - a multi-platform office productivity suite * - * $RCSfile: u2johab.inc,v $ - * $Revision: 1.4 $ - * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify @@ -28,6 +25,8 @@ * ************************************************************************/ +// use generic RTL_TEXTENCODING_JOHAB to get rid of this file + sal_uInt16pair xlat_1_6[17141] = { {0x0020, 0x0020},{0x0021, 0x0021},{0x0022, 0x0022},{0x0023, 0x0023},{0x0024, 0x0024},{0x0025, 0x0025},{0x0026, 0x0026},{0x0027, 0x0027}, {0x0028, 0x0028},{0x0029, 0x0029},{0x002A, 0x002A},{0x002B, 0x002B},{0x002C, 0x002C},{0x002D, 0x002D},{0x002E, 0x002E},{0x002F, 0x002F}, diff --git a/vcl/source/fontsubset/u2prc.inc b/vcl/source/fontsubset/u2prc.inc index 2479d23ebe6f..445461b59653 100644 --- a/vcl/source/fontsubset/u2prc.inc +++ b/vcl/source/fontsubset/u2prc.inc @@ -6,9 +6,6 @@ * * OpenOffice.org - a multi-platform office productivity suite * - * $RCSfile: u2prc.inc,v $ - * $Revision: 1.4 $ - * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify @@ -28,6 +25,8 @@ * ************************************************************************/ +// use generic RTL_TEXTENCODING_ to get rid of this file + sal_uInt16pair xlat_1_4[24035] = { {0x0020, 0x0020},{0x0021, 0x0021},{0x0022, 0x0022},{0x0023, 0x0023},{0x0024, 0x0024},{0x0025, 0x0025},{0x0026, 0x0026},{0x0027, 0x0027}, {0x0028, 0x0028},{0x0029, 0x0029},{0x002A, 0x002A},{0x002B, 0x002B},{0x002C, 0x002C},{0x002D, 0x002D},{0x002E, 0x002E},{0x002F, 0x002F}, diff --git a/vcl/source/fontsubset/u2shiftjis.inc b/vcl/source/fontsubset/u2shiftjis.inc index fb130feaebe2..ebc6f1676784 100644 --- a/vcl/source/fontsubset/u2shiftjis.inc +++ b/vcl/source/fontsubset/u2shiftjis.inc @@ -6,9 +6,6 @@ * * OpenOffice.org - a multi-platform office productivity suite * - * $RCSfile: u2shiftjis.inc,v $ - * $Revision: 1.4 $ - * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify @@ -28,6 +25,8 @@ * ************************************************************************/ +// TODO: use generic RTL_TEXTENCODING_SHIFTJIS to get rid of this file + sal_uInt16pair xlat_1_2[7484] = { {0x0020, 0x0020},{0x0021, 0x0021},{0x0022, 0x0022},{0x0023, 0x0023},{0x0024, 0x0024},{0x0025, 0x0025},{0x0026, 0x0026},{0x0027, 0x0027}, {0x0028, 0x0028},{0x0029, 0x0029},{0x002A, 0x002A},{0x002B, 0x002B},{0x002C, 0x002C},{0x002D, 0x002D},{0x002E, 0x002E},{0x002F, 0x002F}, diff --git a/vcl/source/fontsubset/u2wansung.inc b/vcl/source/fontsubset/u2wansung.inc index 0cb8867f1c2a..b321c9e58bfa 100644 --- a/vcl/source/fontsubset/u2wansung.inc +++ b/vcl/source/fontsubset/u2wansung.inc @@ -6,9 +6,6 @@ * * OpenOffice.org - a multi-platform office productivity suite * - * $RCSfile: u2wansung.inc,v $ - * $Revision: 1.4 $ - * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify @@ -28,6 +25,8 @@ * ************************************************************************/ +// TODO: use generic RTL_TEXTENCODING_WANSUNG to get rid of this file + sal_uInt16pair xlat_1_5[8319] = { {0x0020, 0x0020},{0x0021, 0x0021},{0x0022, 0x0022},{0x0023, 0x0023},{0x0024, 0x0024},{0x0025, 0x0025},{0x0026, 0x0026},{0x0027, 0x0027}, {0x0028, 0x0028},{0x0029, 0x0029},{0x002A, 0x002A},{0x002B, 0x002B},{0x002C, 0x002C},{0x002D, 0x002D},{0x002E, 0x002E},{0x002F, 0x002F}, diff --git a/vcl/source/fontsubset/xlat.c b/vcl/source/fontsubset/xlat.c deleted file mode 100644 index 840850a020da..000000000000 --- a/vcl/source/fontsubset/xlat.c +++ /dev/null @@ -1,187 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: xlat.c,v $ - * $Revision: 1.4 $ - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -/* $Id: xlat.c,v 1.4 2008-04-11 10:19:41 rt Exp $ - * - * Data translation from Unicode to MS encodings - * If the host system provides this functionality - * this file should be rewritten to use it and - * the large translation arrays should be removed - * - * Author: Alexander Gelfenbain - * - */ - -#include "xlat.h" - -#include "u2big5.inc" -#include "u2johab.inc" -#include "u2prc.inc" -#include "u2shiftjis.inc" -#include "u2wansung.inc" - -#define MISSING_CODE 0 - -static sal_uInt16 xlat(sal_uInt16pair p[], sal_uInt32 n, sal_uInt16 src) -{ - int l = 0, r = n - 1, i; - sal_uInt16 t, res = MISSING_CODE; - - do { - i = (l + r) >> 1; - t = p[i].s; - if (src >= t) l = i + 1; - if (src <= t) r = i - 1; - } while (l <= r); - - if (l - r == 2) { - res = p[l-1].d; - } - - return res; -} - -sal_uInt16 TranslateChar12(sal_uInt16 src) -{ - return xlat(xlat_1_2, sizeof(xlat_1_2) / sizeof(xlat_1_2[0]), src); -} - -sal_uInt16 TranslateChar13(sal_uInt16 src) -{ - return xlat(xlat_1_3, sizeof(xlat_1_3) / sizeof(xlat_1_3[0]), src); -} - -sal_uInt16 TranslateChar14(sal_uInt16 src) -{ - return xlat(xlat_1_4, sizeof(xlat_1_4) / sizeof(xlat_1_4[0]), src); -} - -sal_uInt16 TranslateChar15(sal_uInt16 src) -{ - return xlat(xlat_1_5, sizeof(xlat_1_5) / sizeof(xlat_1_5[0]), src); -} - -sal_uInt16 TranslateChar16(sal_uInt16 src) -{ - return xlat(xlat_1_6, sizeof(xlat_1_6) / sizeof(xlat_1_5[0]), src); -} - -void TranslateString12(sal_uInt16 *src, sal_uInt16 *dst, sal_uInt32 n) -{ - sal_uInt32 i; - sal_uInt16 lastS, lastD; - - if (n == 0) return; - - lastD = dst[0] = xlat(xlat_1_2, sizeof(xlat_1_2) / sizeof(xlat_1_2[0]), lastS = src[0]); - - for (i=1; i < n; i++) { - if (src[i] == lastS) { - dst[i] = lastD; - } else { - lastD = dst[i] = xlat(xlat_1_2, sizeof(xlat_1_2) / sizeof(xlat_1_2[0]), lastS = src[i]); - } - } -} - -void TranslateString13(sal_uInt16 *src, sal_uInt16 *dst, sal_uInt32 n) -{ - sal_uInt32 i; - sal_uInt16 lastS, lastD; - - if (n == 0) return; - - lastD = dst[0] = xlat(xlat_1_3, sizeof(xlat_1_3) / sizeof(xlat_1_3[0]), lastS = src[0]); - - for (i=1; i < n; i++) { - if (src[i] == lastS) { - dst[i] = lastD; - } else { - lastD = dst[i] = xlat(xlat_1_3, sizeof(xlat_1_3) / sizeof(xlat_1_3[0]), lastS = src[i]); - } - } -} - -void TranslateString14(sal_uInt16 *src, sal_uInt16 *dst, sal_uInt32 n) -{ - sal_uInt32 i; - sal_uInt16 lastS, lastD; - - if (n == 0) return; - - lastD = dst[0] = xlat(xlat_1_4, sizeof(xlat_1_4) / sizeof(xlat_1_4[0]), lastS = src[0]); - - for (i=1; i < n; i++) { - if (src[i] == lastS) { - dst[i] = lastD; - } else { - lastD = dst[i] = xlat(xlat_1_4, sizeof(xlat_1_4) / sizeof(xlat_1_4[0]), lastS = src[i]); - } - } -} - -void TranslateString15(sal_uInt16 *src, sal_uInt16 *dst, sal_uInt32 n) -{ - sal_uInt32 i; - sal_uInt16 lastS, lastD; - - if (n == 0) return; - - lastD = dst[0] = xlat(xlat_1_5, sizeof(xlat_1_5) / sizeof(xlat_1_5[0]), lastS = src[0]); - - for (i=1; i < n; i++) { - if (src[i] == lastS) { - dst[i] = lastD; - } else { - lastD = dst[i] = xlat(xlat_1_5, sizeof(xlat_1_5) / sizeof(xlat_1_5[0]), lastS = src[i]); - } - } -} - -void TranslateString16(sal_uInt16 *src, sal_uInt16 *dst, sal_uInt32 n) -{ - sal_uInt32 i; - sal_uInt16 lastS, lastD; - - if (n == 0) return; - - lastD = dst[0] = xlat(xlat_1_6, sizeof(xlat_1_6) / sizeof(xlat_1_6[0]), lastS = src[0]); - - for (i=1; i < n; i++) { - if (src[i] == lastS) { - dst[i] = lastD; - } else { - lastD = dst[i] = xlat(xlat_1_6, sizeof(xlat_1_6) / sizeof(xlat_1_6[0]), lastS = src[i]); - } - } -} - - - diff --git a/vcl/source/fontsubset/xlat.cxx b/vcl/source/fontsubset/xlat.cxx new file mode 100644 index 000000000000..27b2f517f4a1 --- /dev/null +++ b/vcl/source/fontsubset/xlat.cxx @@ -0,0 +1,188 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +/* + * + * Data translation from Unicode to MS encodings + * If the host system provides this functionality + * this file should be rewritten to use it and + * the large translation arrays should be removed + * + * Author: Alexander Gelfenbain + * + */ + +#include "xlat.hxx" + +namespace vcl +{ + +// TODO: use generic encoding converters and get rid of the include files below +#include "u2big5.inc" +#include "u2johab.inc" +#include "u2prc.inc" +#include "u2shiftjis.inc" +#include "u2wansung.inc" + +#define MISSING_CODE 0 + +static sal_uInt16 xlat(sal_uInt16pair p[], sal_uInt32 n, sal_uInt16 src) +{ + int l = 0, r = n - 1, i; + sal_uInt16 t, res = MISSING_CODE; + + do { + i = (l + r) >> 1; + t = p[i].s; + if (src >= t) l = i + 1; + if (src <= t) r = i - 1; + } while (l <= r); + + if (l - r == 2) { + res = p[l-1].d; + } + + return res; +} + +sal_uInt16 TranslateChar12(sal_uInt16 src) +{ + return xlat(xlat_1_2, sizeof(xlat_1_2) / sizeof(xlat_1_2[0]), src); +} + +sal_uInt16 TranslateChar13(sal_uInt16 src) +{ + return xlat(xlat_1_3, sizeof(xlat_1_3) / sizeof(xlat_1_3[0]), src); +} + +sal_uInt16 TranslateChar14(sal_uInt16 src) +{ + return xlat(xlat_1_4, sizeof(xlat_1_4) / sizeof(xlat_1_4[0]), src); +} + +sal_uInt16 TranslateChar15(sal_uInt16 src) +{ + return xlat(xlat_1_5, sizeof(xlat_1_5) / sizeof(xlat_1_5[0]), src); +} + +sal_uInt16 TranslateChar16(sal_uInt16 src) +{ + return xlat(xlat_1_6, sizeof(xlat_1_6) / sizeof(xlat_1_5[0]), src); +} + +void TranslateString12(sal_uInt16 *src, sal_uInt16 *dst, sal_uInt32 n) +{ + sal_uInt32 i; + sal_uInt16 lastS, lastD; + + if (n == 0) return; + + lastD = dst[0] = xlat(xlat_1_2, sizeof(xlat_1_2) / sizeof(xlat_1_2[0]), lastS = src[0]); + + for (i=1; i < n; i++) { + if (src[i] == lastS) { + dst[i] = lastD; + } else { + lastD = dst[i] = xlat(xlat_1_2, sizeof(xlat_1_2) / sizeof(xlat_1_2[0]), lastS = src[i]); + } + } +} + +void TranslateString13(sal_uInt16 *src, sal_uInt16 *dst, sal_uInt32 n) +{ + sal_uInt32 i; + sal_uInt16 lastS, lastD; + + if (n == 0) return; + + lastD = dst[0] = xlat(xlat_1_3, sizeof(xlat_1_3) / sizeof(xlat_1_3[0]), lastS = src[0]); + + for (i=1; i < n; i++) { + if (src[i] == lastS) { + dst[i] = lastD; + } else { + lastD = dst[i] = xlat(xlat_1_3, sizeof(xlat_1_3) / sizeof(xlat_1_3[0]), lastS = src[i]); + } + } +} + +void TranslateString14(sal_uInt16 *src, sal_uInt16 *dst, sal_uInt32 n) +{ + sal_uInt32 i; + sal_uInt16 lastS, lastD; + + if (n == 0) return; + + lastD = dst[0] = xlat(xlat_1_4, sizeof(xlat_1_4) / sizeof(xlat_1_4[0]), lastS = src[0]); + + for (i=1; i < n; i++) { + if (src[i] == lastS) { + dst[i] = lastD; + } else { + lastD = dst[i] = xlat(xlat_1_4, sizeof(xlat_1_4) / sizeof(xlat_1_4[0]), lastS = src[i]); + } + } +} + +void TranslateString15(sal_uInt16 *src, sal_uInt16 *dst, sal_uInt32 n) +{ + sal_uInt32 i; + sal_uInt16 lastS, lastD; + + if (n == 0) return; + + lastD = dst[0] = xlat(xlat_1_5, sizeof(xlat_1_5) / sizeof(xlat_1_5[0]), lastS = src[0]); + + for (i=1; i < n; i++) { + if (src[i] == lastS) { + dst[i] = lastD; + } else { + lastD = dst[i] = xlat(xlat_1_5, sizeof(xlat_1_5) / sizeof(xlat_1_5[0]), lastS = src[i]); + } + } +} + +void TranslateString16(sal_uInt16 *src, sal_uInt16 *dst, sal_uInt32 n) +{ + sal_uInt32 i; + sal_uInt16 lastS, lastD; + + if (n == 0) return; + + lastD = dst[0] = xlat(xlat_1_6, sizeof(xlat_1_6) / sizeof(xlat_1_6[0]), lastS = src[0]); + + for (i=1; i < n; i++) { + if (src[i] == lastS) { + dst[i] = lastD; + } else { + lastD = dst[i] = xlat(xlat_1_6, sizeof(xlat_1_6) / sizeof(xlat_1_6[0]), lastS = src[i]); + } + } +} + +} // namespace vcl + diff --git a/vcl/source/fontsubset/xlat.h b/vcl/source/fontsubset/xlat.h deleted file mode 100644 index 86eca1691574..000000000000 --- a/vcl/source/fontsubset/xlat.h +++ /dev/null @@ -1,68 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: xlat.h,v $ - * $Revision: 1.4 $ - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -/* $Id: xlat.h,v 1.4 2008-04-11 10:19:58 rt Exp $ */ - -/*[]---------------------------------------------------[]*/ -/*| |*/ -/*| xlat.h |*/ -/*| |*/ -/*| Author: Alexander Gelfenbain |*/ -/*[]---------------------------------------------------[]*/ - - -#ifndef __XLAT_H -#define __XLAT_H - -#ifdef __cplusplus -extern "C" { -#endif - - -#include "sft.h" - - sal_uInt16 TranslateChar12(sal_uInt16); - sal_uInt16 TranslateChar13(sal_uInt16); - sal_uInt16 TranslateChar14(sal_uInt16); - sal_uInt16 TranslateChar15(sal_uInt16); - sal_uInt16 TranslateChar16(sal_uInt16); - - void TranslateString12(sal_uInt16 *, sal_uInt16 *, sal_uInt32); - void TranslateString13(sal_uInt16 *, sal_uInt16 *, sal_uInt32); - void TranslateString14(sal_uInt16 *, sal_uInt16 *, sal_uInt32); - void TranslateString15(sal_uInt16 *, sal_uInt16 *, sal_uInt32); - void TranslateString16(sal_uInt16 *, sal_uInt16 *, sal_uInt32); - -#ifdef __cplusplus -} -#endif - - -#endif /* __XLAT_H */ diff --git a/vcl/source/fontsubset/xlat.hxx b/vcl/source/fontsubset/xlat.hxx new file mode 100644 index 000000000000..c3bd076f6fbd --- /dev/null +++ b/vcl/source/fontsubset/xlat.hxx @@ -0,0 +1,54 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +/*| Author: Alexander Gelfenbain |*/ + + +#ifndef __XLAT_H +#define __XLAT_H + +#include "sft.hxx" + +namespace vcl +{ +// TODO: sal_UCS4 + + sal_uInt16 TranslateChar12(sal_uInt16); + sal_uInt16 TranslateChar13(sal_uInt16); + sal_uInt16 TranslateChar14(sal_uInt16); + sal_uInt16 TranslateChar15(sal_uInt16); + sal_uInt16 TranslateChar16(sal_uInt16); + + void TranslateString12(sal_uInt16 *, sal_uInt16 *, sal_uInt32); + void TranslateString13(sal_uInt16 *, sal_uInt16 *, sal_uInt32); + void TranslateString14(sal_uInt16 *, sal_uInt16 *, sal_uInt32); + void TranslateString15(sal_uInt16 *, sal_uInt16 *, sal_uInt32); + void TranslateString16(sal_uInt16 *, sal_uInt16 *, sal_uInt32); +} + +#endif /* __XLAT_H */ + diff --git a/vcl/source/gdi/font.cxx b/vcl/source/gdi/font.cxx index 820b053a4211..3bbdba5dad5f 100644 --- a/vcl/source/gdi/font.cxx +++ b/vcl/source/gdi/font.cxx @@ -31,7 +31,7 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_vcl.hxx" -#include "sft.h" +#include "sft.hxx" #include "tools/stream.hxx" #include "tools/vcompat.hxx" @@ -43,6 +43,8 @@ #include <algorithm> +using namespace vcl; + // ======================================================================= DBG_NAME( Font ) diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index 0754f5c5b3dc..bf9e693d081c 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -6902,10 +6902,16 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const String& rText, bool bT if( aAlignOffset.X() || aAlignOffset.Y() ) aAlignOffset = aRotScale.transform( aAlignOffset ); - if( bVertical ) - drawVerticalGlyphs( aGlyphs, aLine, aAlignOffset, aRotScale, fAngle, fXScale, fSkew, nFontHeight ); - else - drawHorizontalGlyphs( aGlyphs, aLine, aAlignOffset, fAngle, fXScale, fSkew, nFontHeight, nPixelFontHeight ); + /* #159153# do not emit an empty glyph vector; this can happen if e.g. the original + string contained only on of the UTF16 BOMs + */ + if( ! aGlyphs.empty() ) + { + if( bVertical ) + drawVerticalGlyphs( aGlyphs, aLine, aAlignOffset, aRotScale, fAngle, fXScale, fSkew, nFontHeight ); + else + drawHorizontalGlyphs( aGlyphs, aLine, aAlignOffset, fAngle, fXScale, fSkew, nFontHeight, nPixelFontHeight ); + } // end textobject aLine.append( "ET\n" ); @@ -9297,14 +9303,24 @@ void PDFWriterImpl::drawJPGBitmap( SvStream& rDCTData, bool bIsTrueColor, const delete pStream; aLine.append( "q " ); - m_aPages.back().appendMappedLength( (sal_Int32)rTargetArea.GetWidth(), aLine, false ); + sal_Int32 nCheckWidth = 0; + m_aPages.back().appendMappedLength( (sal_Int32)rTargetArea.GetWidth(), aLine, false, &nCheckWidth ); aLine.append( " 0 0 " ); - m_aPages.back().appendMappedLength( (sal_Int32)rTargetArea.GetHeight(), aLine, true ); + sal_Int32 nCheckHeight = 0; + m_aPages.back().appendMappedLength( (sal_Int32)rTargetArea.GetHeight(), aLine, true, &nCheckHeight ); aLine.append( ' ' ); m_aPages.back().appendPoint( rTargetArea.BottomLeft(), aLine ); aLine.append( " cm\n/Im" ); aLine.append( it->m_nObject ); aLine.append( " Do Q\n" ); + if( nCheckWidth == 0 || nCheckHeight == 0 ) + { + // #i97512# avoid invalid current matrix + aLine.setLength( 0 ); + aLine.append( "\n%jpeg image /Im" ); + aLine.append( it->m_nObject ); + aLine.append( " scaled to zero size, omitted\n" ); + } writeBuffer( aLine.getStr(), aLine.getLength() ); OStringBuffer aObjName( 16 ); @@ -9325,14 +9341,24 @@ void PDFWriterImpl::drawBitmap( const Point& rDestPoint, const Size& rDestSize, appendNonStrokingColor( rFillColor, aLine ); aLine.append( ' ' ); } - m_aPages.back().appendMappedLength( (sal_Int32)rDestSize.Width(), aLine, false ); + sal_Int32 nCheckWidth = 0; + m_aPages.back().appendMappedLength( (sal_Int32)rDestSize.Width(), aLine, false, &nCheckWidth ); aLine.append( " 0 0 " ); - m_aPages.back().appendMappedLength( (sal_Int32)rDestSize.Height(), aLine, true ); + sal_Int32 nCheckHeight = 0; + m_aPages.back().appendMappedLength( (sal_Int32)rDestSize.Height(), aLine, true, &nCheckHeight ); aLine.append( ' ' ); m_aPages.back().appendPoint( rDestPoint + Point( 0, rDestSize.Height()-1 ), aLine ); aLine.append( " cm\n/Im" ); aLine.append( rBitmap.m_nObject ); aLine.append( " Do Q\n" ); + if( nCheckWidth == 0 || nCheckHeight == 0 ) + { + // #i97512# avoid invalid current matrix + aLine.setLength( 0 ); + aLine.append( "\n%bitmap image /Im" ); + aLine.append( rBitmap.m_nObject ); + aLine.append( " scaled to zero size, omitted\n" ); + } writeBuffer( aLine.getStr(), aLine.getLength() ); } diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx index 0358b25ca153..a96d4dc64b89 100755 --- a/vcl/source/gdi/sallayout.cxx +++ b/vcl/source/gdi/sallayout.cxx @@ -1292,10 +1292,10 @@ void GenericSalLayout::ApplyAsianKerning( const sal_Unicode* pStr, int nLength ) { // ignore code ranges that are not affected by asian punctuation compression const sal_Unicode cHere = pStr[n]; - if( (0x3000 != (cHere & 0xFF00)) && (0x2010 != (cHere & 0xFFF0)) || (0xFF00 != (cHere & 0xFF00)) ) + if( ((0x3000 != (cHere & 0xFF00)) && (0x2010 != (cHere & 0xFFF0))) || (0xFF00 != (cHere & 0xFF00)) ) continue; const sal_Unicode cNext = pStr[n+1]; - if( (0x3000 != (cNext & 0xFF00)) && (0x2010 != (cNext & 0xFFF0)) || (0xFF00 != (cNext & 0xFF00)) ) + if( ((0x3000 != (cNext & 0xFF00)) && (0x2010 != (cNext & 0xFFF0))) || (0xFF00 != (cNext & 0xFF00)) ) continue; // calculate compression values @@ -1773,7 +1773,7 @@ void MultiSalLayout::AdjustLayout( ImplLayoutArgs& rArgs ) int nStartNew[ MAX_FALLBACK ]; int nCharPos[ MAX_FALLBACK ]; sal_Int32 nGlyphAdv[ MAX_FALLBACK ]; - int nValid[ MAX_FALLBACK ]; + int nValid[ MAX_FALLBACK ] = {0}; sal_GlyphId nDummy; Point aPos; diff --git a/vcl/source/helper/smartid.cxx b/vcl/source/helper/smartid.cxx index 7ac7abe0d18b..73ad6f89a21c 100755 --- a/vcl/source/helper/smartid.cxx +++ b/vcl/source/helper/smartid.cxx @@ -262,6 +262,6 @@ BOOL SmartId::operator < ( const SmartId& rRight ) const if ( HasString() ) return rRight.HasString() && rRight.HasNumeric(); else - return rRight.HasString() || !HasNumeric() && rRight.HasNumeric(); + return rRight.HasString() || (!HasNumeric() && rRight.HasNumeric()); } } diff --git a/vcl/source/window/decoview.cxx b/vcl/source/window/decoview.cxx index 90934b382a88..8c6bb2b76463 100644 --- a/vcl/source/window/decoview.cxx +++ b/vcl/source/window/decoview.cxx @@ -944,9 +944,16 @@ static void ImplDrawFrame( OutputDevice* pDev, Rectangle& rRect, Color aColor = bRound ? rStyleSettings.GetShadowColor() : pDev->GetSettings().GetStyleSettings().GetMonoColor(); // when the MonoColor wasn't set, check face color - if ( ( ( bRound && aColor.IsDark() ) || ( aColor == Color( COL_BLACK ) ) && - ( pDev->GetSettings().GetStyleSettings().GetFaceColor().IsDark() ) ) ) + if ( + (bRound && aColor.IsDark()) || + ( + (aColor == Color(COL_BLACK)) && + (pDev->GetSettings().GetStyleSettings().GetFaceColor().IsDark()) + ) + ) + { aColor = Color( COL_WHITE ); + } ImplDrawDPILineRect( pDev, rRect, &aColor, bRound ); } else @@ -1183,7 +1190,7 @@ static void ImplDrawButton( OutputDevice* pDev, Rectangle& rRect, aFillRect.Right(), aFillRect.Top() ) ); aFillRect.Top()++; } - if ( ((nStyle & BUTTON_DRAW_NOBOTTOMSHADOWBORDER | BUTTON_DRAW_FLAT) == (BUTTON_DRAW_NOBOTTOMSHADOWBORDER | BUTTON_DRAW_FLAT)) && + if ( (( (nStyle & BUTTON_DRAW_NOBOTTOMSHADOWBORDER) | BUTTON_DRAW_FLAT) == (BUTTON_DRAW_NOBOTTOMSHADOWBORDER | BUTTON_DRAW_FLAT)) && !(nStyle & (BUTTON_DRAW_PRESSED | BUTTON_DRAW_CHECKED | BUTTON_DRAW_HIGHLIGHT)) ) { pDev->SetFillColor( rStyleSettings.GetDarkShadowColor() ); diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx index c949a59cb222..1fc2b9be703a 100644 --- a/vcl/source/window/dialog.cxx +++ b/vcl/source/window/dialog.cxx @@ -347,7 +347,7 @@ void Dialog::ImplInit( Window* pParent, WinBits nStyle ) { mpWindowImpl->mbFrame = TRUE; mpWindowImpl->mbOverlapWin = TRUE; - SystemWindow::ImplInit( pParent, nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_CLOSEABLE | WB_STANDALONE) | WB_CLOSEABLE, NULL ); + SystemWindow::ImplInit( pParent, (nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_CLOSEABLE | WB_STANDALONE)) | WB_CLOSEABLE, NULL ); // Now set all style bits mpWindowImpl->mnStyle = nStyle; } diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx index 1318f4fa8415..adbc2a8de06e 100644 --- a/vcl/source/window/menu.cxx +++ b/vcl/source/window/menu.cxx @@ -2323,6 +2323,8 @@ Size Menu::ImplCalcSize( Window* pWin ) if ( !bIsMenuBar && ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) ) { Size aImgSz = pData->aImage.GetSizePixel(); + aImgSz.Height() += 4; // add a border for native marks + aImgSz.Width() += 4; // add a border for native marks if ( aImgSz.Width() > aMaxImgSz.Width() ) aMaxImgSz.Width() = aImgSz.Width(); if ( aImgSz.Height() > aMaxImgSz.Height() ) @@ -2336,7 +2338,11 @@ Size Menu::ImplCalcSize( Window* pWin ) { nCheckWidth = nMaxCheckWidth; if (nMenuFlags & MENU_FLAG_SHOWCHECKIMAGES) - nWidth += nCheckWidth + nExtra * 2; + { + // checks / images take the same place + if( ! ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) ) + nWidth += nCheckWidth + nExtra * 2; + } } // Text: @@ -2397,16 +2403,14 @@ Size Menu::ImplCalcSize( Window* pWin ) nCheckPos = (USHORT)nExtra; if (nMenuFlags & MENU_FLAG_SHOWCHECKIMAGES) { - // non-NWF case has an implicit little extra space around - // the symbol; NWF case has not, so image pos needs to - // be distinct in this case + long nImgOrChkWidth = 0; + nImagePos = nCheckPos; if( nMax > 0 ) // NWF case - nImagePos = (USHORT)(nCheckPos + nMax + nExtra ); + nImgOrChkWidth = nMax + nExtra; else // non NWF case - nImagePos = (USHORT)(nCheckPos + nFontHeight/2 + gfxExtra ); - nTextPos = (USHORT)(nImagePos+aMaxImgSz.Width()); - if ( aMaxImgSz.Width() ) - nTextPos = nTextPos + gfxExtra; + nImgOrChkWidth = nFontHeight/2 + gfxExtra; + nImgOrChkWidth = Max( nImgOrChkWidth, aMaxImgSz.Width() + gfxExtra ); + nTextPos = (USHORT)(nImagePos + nImgOrChkWidth); } else { @@ -2464,6 +2468,45 @@ Size Menu::ImplCalcSize( Window* pWin ) return aSz; } +static void ImplPaintCheckBackground( Window* i_pWindow, const Rectangle& i_rRect, bool i_bHighlight ) +{ + BOOL bNativeOk = FALSE; + if( i_pWindow->IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) ) + { + ImplControlValue aControlValue; + Region aCtrlRegion( i_rRect ); + ControlState nState = CTRL_STATE_PRESSED | CTRL_STATE_ENABLED; + + aControlValue.setTristateVal( BUTTONVALUE_ON ); + + bNativeOk = i_pWindow->DrawNativeControl( CTRL_TOOLBAR, PART_BUTTON, + aCtrlRegion, nState, aControlValue, + rtl::OUString() ); + } + + if( ! bNativeOk ) + { + const StyleSettings& rSettings = i_pWindow->GetSettings().GetStyleSettings(); + if( i_bHighlight ) + { + i_pWindow->Push( PUSH_ALL ); + Color aCol = rSettings.GetMenuHighlightTextColor(); + i_pWindow->SetFillColor( rSettings.GetMenuHighlightTextColor() ); + if( aCol.IsDark() ) + aCol.IncreaseLuminance( 128 ); + else + aCol.DecreaseLuminance( 128 ); + i_pWindow->SetLineColor( aCol ); + Polygon aPoly( i_rRect ); + PolyPolygon aPolyPoly( aPoly ); + i_pWindow->DrawTransparent( aPolyPoly, 20 ); + i_pWindow->Pop(); + } + else + i_pWindow->DrawSelectionBackground( i_rRect, 1, FALSE, TRUE, FALSE ); + } +} + void Menu::ImplPaint( Window* pWin, USHORT nBorder, long nStartY, MenuItemData* pThisItemOnly, BOOL bHighlighted, bool bLayout ) const { // Fuer Symbole: nFontHeight x nFontHeight @@ -2537,15 +2580,89 @@ void Menu::ImplPaint( Window* pWin, USHORT nBorder, long nStartY, MenuItemData* pWin->SetLineColor(); } + Rectangle aOuterCheckRect( Point( aPos.X()+nCheckPos, aPos.Y() ), Size( pData->aSz.Height(), pData->aSz.Height() ) ); + aOuterCheckRect.Left() += 1; + aOuterCheckRect.Right() -= 1; + aOuterCheckRect.Top() += 1; + aOuterCheckRect.Bottom() -= 1; + + // CheckMark + if ( !bLayout && !bIsMenuBar && pData->HasCheck() ) + { + // draw selection transparent marker if checked + // onto that either a checkmark or the item image + // will be painted + // however do not do this if native checks will be painted since + // the selection color too often does not fit the theme's check and/or radio + + if( ! ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) ) + { + if ( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, + (pData->nBits & MIB_RADIOCHECK) + ? PART_MENU_ITEM_CHECK_MARK + : PART_MENU_ITEM_RADIO_MARK ) ) + { + ControlPart nPart = ((pData->nBits & MIB_RADIOCHECK) + ? PART_MENU_ITEM_RADIO_MARK + : PART_MENU_ITEM_CHECK_MARK); + + ControlState nState = 0; + + if ( pData->bChecked ) + nState |= CTRL_STATE_PRESSED; + + if ( pData->bEnabled ) + nState |= CTRL_STATE_ENABLED; + + if ( bHighlighted ) + nState |= CTRL_STATE_SELECTED; + + long nCtrlHeight = (pData->nBits & MIB_RADIOCHECK) ? nCheckHeight : nRadioHeight; + aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - nCtrlHeight)/2; + aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - nCtrlHeight)/2; + + Rectangle aCheckRect( aTmpPos, Size( nCtrlHeight, nCtrlHeight ) ); + pWin->DrawNativeControl( CTRL_MENU_POPUP, nPart, + Region( aCheckRect ), + nState, + ImplControlValue(), + OUString() ); + } + else if ( pData->bChecked ) // by default do nothing for unchecked items + { + ImplPaintCheckBackground( pWin, aOuterCheckRect, pThisItemOnly && bHighlighted ); + + SymbolType eSymbol; + Size aSymbolSize; + if ( pData->nBits & MIB_RADIOCHECK ) + { + eSymbol = SYMBOL_RADIOCHECKMARK; + aSymbolSize = Size( nFontHeight/2, nFontHeight/2 ); + } + else + { + eSymbol = SYMBOL_CHECKMARK; + aSymbolSize = Size( (nFontHeight*25)/40, nFontHeight/2 ); + } + aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - aSymbolSize.Width())/2; + aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - aSymbolSize.Height())/2; + Rectangle aRect( aTmpPos, aSymbolSize ); + aDecoView.DrawSymbol( aRect, eSymbol, pWin->GetTextColor(), nSymbolStyle ); + } + } + } + // Image: if ( !bLayout && !bIsMenuBar && ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) ) { // Don't render an image for a check thing if ((nMenuFlags & MENU_FLAG_SHOWCHECKIMAGES) || !pData->HasCheck() ) { - aTmpPos.Y() = aPos.Y(); - aTmpPos.X() = aPos.X() + nImagePos; - aTmpPos.Y() += (pData->aSz.Height()-pData->aImage.GetSizePixel().Height())/2; + if( pData->bChecked ) + ImplPaintCheckBackground( pWin, aOuterCheckRect, pThisItemOnly && bHighlighted ); + aTmpPos = aOuterCheckRect.TopLeft(); + aTmpPos.X() += (aOuterCheckRect.GetWidth()-pData->aImage.GetSizePixel().Width())/2; + aTmpPos.Y() += (aOuterCheckRect.GetHeight()-pData->aImage.GetSizePixel().Height())/2; pWin->DrawImage( aTmpPos, pData->aImage, nImageStyle ); } } @@ -2598,65 +2715,6 @@ void Menu::ImplPaint( Window* pWin, USHORT nBorder, long nStartY, MenuItemData* pWin->DrawCtrlText( aTmpPos, aAccText, 0, aAccText.Len(), nTextStyle ); } - // CheckMark - if ( !bLayout && !bIsMenuBar && pData->HasCheck() ) - { - if ( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, - (pData->nBits & MIB_RADIOCHECK) - ? PART_MENU_ITEM_CHECK_MARK - : PART_MENU_ITEM_RADIO_MARK ) ) - { - ControlPart nPart = ((pData->nBits & MIB_RADIOCHECK) - ? PART_MENU_ITEM_RADIO_MARK - : PART_MENU_ITEM_CHECK_MARK); - - ControlState nState = 0; - - if ( pData->bChecked ) - nState |= CTRL_STATE_PRESSED; - - if ( pData->bEnabled ) - nState |= CTRL_STATE_ENABLED; - - if ( bHighlighted ) - nState |= CTRL_STATE_SELECTED; - - aTmpPos.X() = aPos.X() + nCheckPos; - aTmpPos.Y() = aPos.Y() + nCheckPos; - - long nCtrlHeight = (pData->nBits & MIB_RADIOCHECK) ? nCheckHeight : nRadioHeight; - Rectangle aCheckRect( aTmpPos, Size( nCtrlHeight, nCtrlHeight ) ); - pWin->DrawNativeControl( CTRL_MENU_POPUP, nPart, - Region( aCheckRect ), - nState, - ImplControlValue(), - OUString() ); - } - else if ( pData->bChecked ) // by default do nothing for unchecked items - { - Rectangle aRect; - SymbolType eSymbol; - aTmpPos.Y() = aPos.Y(); - aTmpPos.Y() += nExtra/2; - aTmpPos.Y() += pData->aSz.Height() / 2; - if ( pData->nBits & MIB_RADIOCHECK ) - { - aTmpPos.X() = aPos.X() + nCheckPos; - eSymbol = SYMBOL_RADIOCHECKMARK; - aTmpPos.Y() -= nFontHeight/4; - aRect = Rectangle( aTmpPos, Size( nFontHeight/2, nFontHeight/2 ) ); - } - else - { - aTmpPos.X() = aPos.X() + nCheckPos; - eSymbol = SYMBOL_CHECKMARK; - aTmpPos.Y() -= nFontHeight/4; - aRect = Rectangle( aTmpPos, Size( (nFontHeight*25)/40, nFontHeight/2 ) ); - } - aDecoView.DrawSymbol( aRect, eSymbol, pWin->GetTextColor(), nSymbolStyle ); - } - } - // SubMenu? if ( !bLayout && !bIsMenuBar && pData->pSubMenu ) { diff --git a/vcl/source/window/splitwin.cxx b/vcl/source/window/splitwin.cxx index a7a21fb840ad..1e66849db73a 100644 --- a/vcl/source/window/splitwin.cxx +++ b/vcl/source/window/splitwin.cxx @@ -1879,7 +1879,7 @@ void SplitWindow::ImplDrawButtonRect( const Rectangle& rRect, long nSize ) DrawPixel( Point( i+1, nCenter-2+1 ), rStyleSettings.GetShadowColor() ); } i++; - if ( (i < nEx1) || (i > nEx2 ) && (i < nRight-3) ) + if ( (i < nEx1) || ((i > nEx2 ) && (i < nRight-3)) ) { DrawPixel( Point( i, nCenter+2 ), rStyleSettings.GetLightColor() ); DrawPixel( Point( i+1, nCenter+2+1 ), rStyleSettings.GetShadowColor() ); @@ -1909,7 +1909,7 @@ void SplitWindow::ImplDrawButtonRect( const Rectangle& rRect, long nSize ) DrawPixel( Point( nCenter-2+1, i+1 ), rStyleSettings.GetShadowColor() ); } i++; - if ( (i < nEx1) || (i > nEx2 ) && (i < nBottom-3) ) + if ( (i < nEx1) || ((i > nEx2 ) && (i < nBottom-3)) ) { DrawPixel( Point( nCenter+2, i ), rStyleSettings.GetLightColor() ); DrawPixel( Point( nCenter+2+1, i+1 ), rStyleSettings.GetShadowColor() ); diff --git a/vcl/source/window/winproc.cxx b/vcl/source/window/winproc.cxx index a8be05bf4909..0dcf0d686cb2 100644 --- a/vcl/source/window/winproc.cxx +++ b/vcl/source/window/winproc.cxx @@ -1622,8 +1622,10 @@ void ImplHandleResize( Window* pWindow, long nNewWidth, long nNewHeight ) ImplDestroyHelpWindow( true ); } - if ( (nNewWidth > 0) && (nNewHeight > 0) || - pWindow->ImplGetWindow()->ImplGetWindowImpl()->mbAllResize ) + if ( + (nNewWidth > 0 && nNewHeight > 0) || + pWindow->ImplGetWindow()->ImplGetWindowImpl()->mbAllResize + ) { if ( (nNewWidth != pWindow->GetOutputWidthPixel()) || (nNewHeight != pWindow->GetOutputHeightPixel()) ) { -- cgit