2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2007-2009 Torch Mobile, Inc.
4 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
5 * Copyright (C) 2008 Holger Hans Peter Freyther
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "AffineTransform.h"
33 #include "FloatRect.h"
34 #include "FontCache.h"
36 #include "FontFallbackList.h"
37 #include "GlyphBuffer.h"
38 #include "GraphicsContext.h"
40 #include "NotImplemented.h"
42 #include "WidthIterator.h"
43 #include <wtf/MathExtras.h>
44 #include <wtf/OwnPtr.h>
45 #include <wtf/unicode/Unicode.h>
49 using namespace WTF::Unicode;
53 HDC g_screenDC = GetDC(0);
55 class ScreenDcReleaser {
59 ReleaseDC(0, g_screenDC);
63 ScreenDcReleaser releaseScreenDc;
65 void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fontData, const GlyphBuffer& glyphBuffer,
66 int from, int numGlyphs, const FloatPoint& point) const
68 graphicsContext->drawText(fontData, glyphBuffer, from, numGlyphs, point);
71 class TextRunComponent {
73 TextRunComponent() : m_textRun(0, 0) {}
74 TextRunComponent(const UChar *start, int length, const TextRun& parentTextRun, const Font &font, int offset);
75 TextRunComponent(int spaces, const Font &font, int offset);
76 ~TextRunComponent() { m_textRun; }
78 bool isSpace() const { return m_spaces; }
79 int textLength() const { return m_spaces ? m_spaces : m_textRun.length(); }
87 TextRunComponent::TextRunComponent(const UChar *start, int length, const TextRun& parentTextRun, const Font &font, int o)
88 : m_textRun(start, length, parentTextRun.allowTabs(), 0, 0
89 , parentTextRun.allowsTrailingExpansion() ? TextRun::AllowTrailingExpansion : TextRun::ForbidTrailingExpansion
90 , parentTextRun.direction()
91 , parentTextRun.directionalOverride())
95 WidthIterator it(&font, m_textRun);
96 it.advance(m_textRun.length(), 0);
97 m_width = it.m_runWidthSoFar;
100 TextRunComponent::TextRunComponent(int s, const Font &font, int o)
105 m_width = s * font.primaryFont()->widthForGlyph(' ');
108 typedef Vector<TextRunComponent, 128> TextRunComponents;
110 static int generateComponents(TextRunComponents* components, const Font &font, const TextRun &run)
112 int letterSpacing = font.letterSpacing();
113 int wordSpacing = font.wordSpacing();
114 int padding = run.expansion();
117 for (int i = 0; i < run.length(); i++)
118 if (Font::treatAsSpace(run[i]))
124 // need to draw every letter on it's own
126 if (Font::treatAsSpace(run[0])) {
129 add = padding/numSpaces;
133 components->append(TextRunComponent(1, font, offset));
134 offset += add + letterSpacing + components->last().m_width;
137 for (int i = 1; i < run.length(); ++i) {
139 if (isHighSurrogate(ch) && isLowSurrogate(run[i-1]))
140 ch = surrogateToUcs4(ch, run[i-1]);
141 if (isLowSurrogate(ch) || category(ch) == Mark_NonSpacing)
143 if (Font::treatAsSpace(run[i])) {
146 components->append(TextRunComponent(run.characters() + start, i - start,
148 offset += components->last().m_width + letterSpacing;
151 add = padding/numSpaces;
155 components->append(TextRunComponent(1, font, offset));
156 offset += wordSpacing + add + components->last().m_width + letterSpacing;
161 components->append(TextRunComponent(run.characters() + start, i - start,
164 offset += components->last().m_width + letterSpacing;
168 if (run.length() - start > 0) {
169 components->append(TextRunComponent(run.characters() + start, run.length() - start,
172 offset += components->last().m_width;
174 offset += letterSpacing;
177 for (int i = 0; i < run.length(); ++i) {
178 if (Font::treatAsSpace(run[i])) {
180 components->append(TextRunComponent(run.characters() + start, i - start,
183 offset += components->last().m_width;
187 add = padding/numSpaces;
191 components->append(TextRunComponent(1, font, offset));
192 offset += add + components->last().m_width;
194 offset += wordSpacing;
198 if (run.length() - start > 0) {
199 components->append(TextRunComponent(run.characters() + start, run.length() - start,
202 offset += components->last().m_width;
208 void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point,
209 int from, int to) const
216 TextRunComponents components;
217 int w = generateComponents(&components, *this, run);
220 for (int i = 0; i < (int)components.size(); ++i) {
221 const TextRunComponent& comp = components.at(i);
222 int len = comp.textLength();
223 int curEnd = curPos + len;
224 if (curPos < to && from < curEnd && !comp.isSpace()) {
225 FloatPoint pt = point;
227 pt.setX(point.x() + w - comp.m_offset - comp.m_width);
229 pt.setX(point.x() + comp.m_offset);
230 drawSimpleText(context, comp.m_textRun, pt, from - curPos, std::min(to, curEnd) - curPos);
238 void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
243 float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
245 TextRunComponents components;
246 int w = generateComponents(&components, *this, run);
250 int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, bool includePartialGlyphs) const
252 // FIXME: This truncation is not a problem for HTML, but only affects SVG, which passes floating-point numbers
253 // to Font::offsetForPosition(). Bug http://webkit.org/b/40673 tracks fixing this problem.
254 int position = static_cast<int>(xFloat);
256 TextRunComponents components;
257 int w = generateComponents(&components, *this, run);
264 for (size_t i = 0; i < components.size(); ++i) {
265 const TextRunComponent& comp = components.at(i);
266 int xe = w - comp.m_offset;
267 int xs = xe - comp.m_width;
269 return offset + (comp.isSpace()
270 ? static_cast<int>((position - xe) * comp.m_spaces / std::max(1.f, comp.m_width) + 0.5)
271 : offsetForPositionForSimpleText(comp.m_textRun, position - xs, includePartialGlyphs));
273 offset += comp.textLength();
276 for (size_t i = 0; i < components.size(); ++i) {
277 const TextRunComponent& comp = components.at(i);
278 int xs = comp.m_offset;
279 int xe = xs + comp.m_width;
280 if (position <= xe) {
281 if (position - xs >= xe)
282 return offset + comp.textLength();
283 return offset + (comp.isSpace()
284 ? static_cast<int>((position - xs) * comp.m_spaces / std::max(1.f, comp.m_width) + 0.5)
285 : offsetForPositionForSimpleText(comp.m_textRun, position - xs, includePartialGlyphs));
287 offset += comp.textLength();
294 static float cursorToX(const Font* font, const TextRunComponents& components, int width, bool rtl, int cursor)
297 for (size_t i = 0; i < components.size(); ++i) {
298 const TextRunComponent& comp = components.at(i);
299 if (start + comp.textLength() <= cursor) {
300 start += comp.textLength();
303 int xs = comp.m_offset;
305 xs = width - xs - comp.m_width;
307 int pos = cursor - start;
308 if (comp.isSpace()) {
310 pos = comp.textLength() - pos;
311 return xs + pos * comp.m_width / comp.m_spaces;
313 WidthIterator it(font, comp.m_textRun);
315 return xs + it.m_runWidthSoFar;
320 FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& pt,
321 int h, int from, int to) const
323 TextRunComponents components;
324 int w = generateComponents(&components, *this, run);
326 if (!from && to == run.length())
327 return FloatRect(pt.x(), pt.y(), w, h);
329 float x1 = cursorToX(this, components, w, run.rtl(), from);
330 float x2 = cursorToX(this, components, w, run.rtl(), to);
334 return FloatRect(pt.x() + x1, pt.y(), x2 - x1, h);
337 bool Font::canReturnFallbackFontsForComplexText()
342 bool Font::canExpandAroundIdeographsInComplexText()
347 } // namespace WebCore