0N/A/*
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A *
0N/A */
0N/A
0N/A/*
0N/A *
3171N/A * (C) Copyright IBM Corp. 1998-2010 - All Rights Reserved
0N/A *
0N/A */
0N/A
0N/A#include "LETypes.h"
0N/A#include "OpenTypeTables.h"
0N/A#include "OpenTypeUtilities.h"
0N/A#include "LESwaps.h"
0N/A
1693N/AU_NAMESPACE_BEGIN
1693N/A
0N/A//
0N/A// Finds the high bit by binary searching
0N/A// through the bits in n.
0N/A//
0N/Ale_int8 OpenTypeUtilities::highBit(le_int32 value)
0N/A{
0N/A if (value <= 0) {
0N/A return -32;
0N/A }
0N/A
0N/A le_uint8 bit = 0;
0N/A
0N/A if (value >= 1 << 16) {
0N/A value >>= 16;
0N/A bit += 16;
0N/A }
0N/A
0N/A if (value >= 1 << 8) {
0N/A value >>= 8;
0N/A bit += 8;
0N/A }
0N/A
0N/A if (value >= 1 << 4) {
0N/A value >>= 4;
0N/A bit += 4;
0N/A }
0N/A
0N/A if (value >= 1 << 2) {
0N/A value >>= 2;
0N/A bit += 2;
0N/A }
0N/A
0N/A if (value >= 1 << 1) {
0N/A value >>= 1;
0N/A bit += 1;
0N/A }
0N/A
0N/A return bit;
0N/A}
0N/A
5980N/A
5980N/AOffset OpenTypeUtilities::getTagOffset(LETag tag, const LEReferenceToArrayOf<TagAndOffsetRecord> &records, LEErrorCode &success)
0N/A{
5980N/A if(LE_FAILURE(success)) return 0;
0N/A
5980N/A le_uint32 recordCount = records.getCount();
5980N/A le_uint8 bit = highBit(recordCount);
5980N/A le_int32 power = 1 << bit;
5980N/A le_int32 extra = recordCount - power;
5980N/A le_int32 probe = power;
5980N/A le_int32 index = 0;
5980N/A
5980N/A {
5980N/A const ATag &aTag = records.getAlias(extra,success)->tag;
5980N/A if (SWAPT(aTag) <= tag) {
5980N/A index = extra;
0N/A }
5980N/A }
0N/A
5980N/A while (probe > (1 << 0) && LE_SUCCESS(success)) {
5980N/A probe >>= 1;
0N/A
5980N/A {
5980N/A const ATag &aTag = records.getAlias(index+probe,success)->tag;
5980N/A if (SWAPT(aTag) <= tag) {
5980N/A index += probe;
5980N/A }
0N/A }
5980N/A }
0N/A
5980N/A {
5980N/A const ATag &aTag = records.getAlias(index,success)->tag;
5980N/A if (SWAPT(aTag) == tag) {
5980N/A return SWAPW(records.getAlias(index,success)->offset);
0N/A }
5980N/A }
0N/A
5980N/A return 0;
0N/A}
0N/A
5980N/Ale_int32 OpenTypeUtilities::getGlyphRangeIndex(TTGlyphID glyphID, const LEReferenceToArrayOf<GlyphRangeRecord> &records, LEErrorCode &success)
0N/A{
5980N/A if(LE_FAILURE(success)) return -1;
5980N/A
5980N/A le_uint32 recordCount = records.getCount();
0N/A le_uint8 bit = highBit(recordCount);
0N/A le_int32 power = 1 << bit;
0N/A le_int32 extra = recordCount - power;
0N/A le_int32 probe = power;
0N/A le_int32 range = 0;
0N/A
5980N/A if (recordCount == 0) {
5980N/A return -1;
5980N/A }
3171N/A
5980N/A if (SWAPW(records(extra,success).firstGlyph) <= glyphID) {
0N/A range = extra;
0N/A }
0N/A
5980N/A while (probe > (1 << 0) && LE_SUCCESS(success)) {
0N/A probe >>= 1;
0N/A
5980N/A if (SWAPW(records(range + probe,success).firstGlyph) <= glyphID) {
0N/A range += probe;
0N/A }
0N/A }
0N/A
5980N/A if (SWAPW(records(range,success).firstGlyph) <= glyphID && SWAPW(records(range,success).lastGlyph) >= glyphID) {
0N/A return range;
0N/A }
0N/A
0N/A return -1;
0N/A}
0N/A
0N/Ale_int32 OpenTypeUtilities::search(le_uint32 value, const le_uint32 array[], le_int32 count)
0N/A{
0N/A le_int32 power = 1 << highBit(count);
0N/A le_int32 extra = count - power;
0N/A le_int32 probe = power;
0N/A le_int32 index = 0;
0N/A
0N/A if (value >= array[extra]) {
0N/A index = extra;
0N/A }
0N/A
0N/A while (probe > (1 << 0)) {
0N/A probe >>= 1;
0N/A
0N/A if (value >= array[index + probe]) {
0N/A index += probe;
0N/A }
0N/A }
0N/A
0N/A return index;
0N/A}
0N/A
0N/Ale_int32 OpenTypeUtilities::search(le_uint16 value, const le_uint16 array[], le_int32 count)
0N/A{
0N/A le_int32 power = 1 << highBit(count);
0N/A le_int32 extra = count - power;
0N/A le_int32 probe = power;
0N/A le_int32 index = 0;
0N/A
0N/A if (value >= array[extra]) {
0N/A index = extra;
0N/A }
0N/A
0N/A while (probe > (1 << 0)) {
0N/A probe >>= 1;
0N/A
0N/A if (value >= array[index + probe]) {
0N/A index += probe;
0N/A }
0N/A }
0N/A
0N/A return index;
0N/A}
0N/A
0N/A//
0N/A// Straight insertion sort from Knuth vol. III, pg. 81
0N/A//
0N/Avoid OpenTypeUtilities::sort(le_uint16 *array, le_int32 count)
0N/A{
0N/A for (le_int32 j = 1; j < count; j += 1) {
0N/A le_int32 i;
0N/A le_uint16 v = array[j];
0N/A
0N/A for (i = j - 1; i >= 0; i -= 1) {
0N/A if (v >= array[i]) {
0N/A break;
0N/A }
0N/A
0N/A array[i + 1] = array[i];
0N/A }
0N/A
0N/A array[i + 1] = v;
0N/A }
0N/A}
1693N/A
5980N/AU_NAMESPACE_END
1693N/A
5980N/A#if LE_ASSERT_BAD_FONT
5980N/A#include <stdio.h>
5980N/A
5980N/Astatic const char *letagToStr(LETag tag, char *str) {
5980N/A str[0]= 0xFF & (tag>>24);
5980N/A str[1]= 0xFF & (tag>>16);
5980N/A str[2]= 0xFF & (tag>>8);
5980N/A str[3]= 0xFF & (tag>>0);
5980N/A str[4]= 0;
5980N/A return str;
5980N/A}
5980N/A
5980N/AU_CAPI void U_EXPORT2 _debug_LETableReference(const char *f, int l, const char *msg, const LETableReference *what, const void *ptr, size_t len) {
5980N/A char tagbuf[5];
1693N/A
5980N/A fprintf(stderr, "%s:%d: LETableReference@0x%p: ", f, l, what);
5980N/A fprintf(stderr, msg, ptr, len);
5980N/A fprintf(stderr, "\n");
5980N/A
5980N/A for(int depth=0;depth<10&&(what!=NULL);depth++) {
5980N/A for(int i=0;i<depth;i++) {
5980N/A fprintf(stderr, " "); // indent
5980N/A }
5980N/A if(!what->isValid()) {
5980N/A fprintf(stderr, "(invalid)");
5980N/A }
5980N/A fprintf(stderr, "@%p: tag (%s) font (0x%p), [0x%p+0x%lx]\n", what, letagToStr(what->getTag(), tagbuf), what->getFont(),
5980N/A what->getAlias(), what->getLength());
5980N/A
5980N/A what = what->getParent();
5980N/A }
5980N/A}
5980N/A#endif