1/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation.  Oracle designates this
7 * particular file as subject to the "Classpath" exception as provided
8 * by Oracle in the LICENSE file that accompanied this code.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26/*
27 *******************************************************************************
28 *
29 *   Copyright (C) 1999-2007, International Business Machines
30 *   Corporation and others.  All Rights Reserved.
31 *
32 *******************************************************************************
33 *   file name:  LEFontInstance.cpp
34 *
35 *   created on: 02/06/2003
36 *   created by: Eric R. Mader
37 */
38
39#include "LETypes.h"
40#include "LEScripts.h"
41#include "LEFontInstance.h"
42#include "LEGlyphStorage.h"
43
44U_NAMESPACE_BEGIN
45
46UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LEFontInstance)
47
48LECharMapper::~LECharMapper()
49{
50    // nothing to do.
51}
52
53LEFontInstance::~LEFontInstance()
54{
55    // nothing to do
56}
57
58const LEFontInstance *LEFontInstance::getSubFont(const LEUnicode chars[], le_int32 *offset, le_int32 limit,
59                                                       le_int32 script, LEErrorCode &success) const
60{
61    if (LE_FAILURE(success)) {
62        return NULL;
63    }
64
65    if (chars == NULL || *offset < 0 || limit < 0 || *offset >= limit || script < 0 || script >= scriptCodeCount) {
66        success = LE_ILLEGAL_ARGUMENT_ERROR;
67        return NULL;
68    }
69
70    *offset = limit;
71    return this;
72}
73
74void LEFontInstance::mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count,
75                                      le_bool reverse, const LECharMapper *mapper, le_bool filterZeroWidth, LEGlyphStorage &glyphStorage) const
76{
77    le_int32 i, out = 0, dir = 1;
78
79    if (reverse) {
80        out = count - 1;
81        dir = -1;
82    }
83
84    for (i = offset; i < offset + count; i += 1, out += dir) {
85        LEUnicode16 high = chars[i];
86        LEUnicode32 code = high;
87
88        if (i < offset + count - 1 && high >= 0xD800 && high <= 0xDBFF) {
89            LEUnicode16 low = chars[i + 1];
90
91            if (low >= 0xDC00 && low <= 0xDFFF) {
92                code = (high - 0xD800) * 0x400 + low - 0xDC00 + 0x10000;
93            }
94        }
95
96        glyphStorage[out] = mapCharToGlyph(code, mapper, filterZeroWidth);
97
98        if (code >= 0x10000) {
99            i += 1;
100            glyphStorage[out += dir] = 0xFFFF;
101        }
102    }
103}
104
105LEGlyphID LEFontInstance::mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper) const
106{
107    return mapCharToGlyph(ch, mapper, TRUE);
108}
109
110LEGlyphID LEFontInstance::mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper, le_bool filterZeroWidth) const
111{
112    LEUnicode32 mappedChar = mapper->mapChar(ch);
113
114    if (mappedChar == 0xFFFE || mappedChar == 0xFFFF) {
115        return 0xFFFF;
116    }
117
118    if (filterZeroWidth && (mappedChar == 0x200C || mappedChar == 0x200D)) {
119        return canDisplay(mappedChar)? 0x0001 : 0xFFFF;
120    }
121
122    return mapCharToGlyph(mappedChar);
123}
124
125le_bool LEFontInstance::canDisplay(LEUnicode32 ch) const
126{
127    return LE_GET_GLYPH(mapCharToGlyph(ch)) != 0;
128}
129
130float LEFontInstance::xUnitsToPoints(float xUnits) const
131{
132    return (xUnits * getXPixelsPerEm()) / (float) getUnitsPerEM();
133}
134
135float LEFontInstance::yUnitsToPoints(float yUnits) const
136{
137    return (yUnits * getYPixelsPerEm()) / (float) getUnitsPerEM();
138}
139
140void LEFontInstance::unitsToPoints(LEPoint &units, LEPoint &points) const
141{
142    points.fX = xUnitsToPoints(units.fX);
143    points.fY = yUnitsToPoints(units.fY);
144}
145
146float LEFontInstance::xPixelsToUnits(float xPixels) const
147{
148    return (xPixels * getUnitsPerEM()) / (float) getXPixelsPerEm();
149}
150
151float LEFontInstance::yPixelsToUnits(float yPixels) const
152{
153    return (yPixels * getUnitsPerEM()) / (float) getYPixelsPerEm();
154}
155
156void LEFontInstance::pixelsToUnits(LEPoint &pixels, LEPoint &units) const
157{
158    units.fX = xPixelsToUnits(pixels.fX);
159    units.fY = yPixelsToUnits(pixels.fY);
160}
161
162void LEFontInstance::transformFunits(float xFunits, float yFunits, LEPoint &pixels) const
163{
164    pixels.fX = xUnitsToPoints(xFunits) * getScaleFactorX();
165    pixels.fY = yUnitsToPoints(yFunits) * getScaleFactorY();
166}
167
168le_int32 LEFontInstance::getLineHeight() const
169{
170    return getAscent() + getDescent() + getLeading();
171}
172
173U_NAMESPACE_END
174
175