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 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 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 "FontGlyphs.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>
48 using namespace WTF::Unicode;
52 HDC g_screenDC = GetDC(0);
54 class ScreenDcReleaser {
58 ReleaseDC(0, g_screenDC);
62 ScreenDcReleaser releaseScreenDc;
64 void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fontData, const GlyphBuffer& glyphBuffer,
65 int from, int numGlyphs, const FloatPoint& point) const
67 graphicsContext->drawText(fontData, glyphBuffer, from, numGlyphs, point);
70 class TextRunComponent {
72 TextRunComponent() : m_textRun(0, 0) {}
73 TextRunComponent(const UChar *start, int length, const TextRun& parentTextRun, const Font &font, int offset);
74 TextRunComponent(int spaces, const Font &font, int offset);
75 ~TextRunComponent() { m_textRun; }
77 bool isSpace() const { return m_spaces; }
78 int textLength() const { return m_spaces ? m_spaces : m_textRun.length(); }
86 TextRunComponent::TextRunComponent(const UChar *start, int length, const TextRun& parentTextRun, const Font &font, int o)
87 : m_textRun(start, length, 0, 0
88 , parentTextRun.allowsTrailingExpansion() ? TextRun::AllowTrailingExpansion : TextRun::ForbidTrailingExpansion
89 , parentTextRun.direction()
90 , parentTextRun.directionalOverride())
94 m_textRun.setTabSize(parentTextRun.allowTabs(), parentTextRun.tabSize());
96 WidthIterator it(&font, m_textRun);
97 it.advance(m_textRun.length(), 0);
98 m_width = it.m_runWidthSoFar;
101 TextRunComponent::TextRunComponent(int s, const Font &font, int o)
106 m_width = s * font.primaryFont()->widthForGlyph(' ');
109 typedef Vector<TextRunComponent, 128> TextRunComponents;
111 static int generateComponents(TextRunComponents* components, const Font &font, const TextRun &run)
113 int letterSpacing = font.letterSpacing();
114 int wordSpacing = font.wordSpacing();
115 int padding = run.expansion();
118 for (int i = 0; i < run.length(); i++)
119 if (Font::treatAsSpace(run[i]))
125 // need to draw every letter on it's own
127 if (Font::treatAsSpace(run[0])) {
130 add = padding/numSpaces;
134 components->append(TextRunComponent(1, font, offset));
135 offset += add + letterSpacing + components->last().m_width;
138 for (int i = 1; i < run.length(); ++i) {
140 if (U16_IS_LEAD(ch) && U16_IS_TRAIL(run[i-1]))
141 ch = U16_GET_SUPPLEMENTARY(ch, run[i-1]);
142 if (U16_IS_TRAIL(ch) || U_GET_GC_MASK(ch) & U_GC_MN_MASK)
144 if (Font::treatAsSpace(run[i])) {
147 components->append(TextRunComponent(run.characters16() + start, i - start,
149 offset += components->last().m_width + letterSpacing;
152 add = padding/numSpaces;
156 components->append(TextRunComponent(1, font, offset));
157 offset += wordSpacing + add + components->last().m_width + letterSpacing;
162 components->append(TextRunComponent(run.characters16() + start, i - start,
165 offset += components->last().m_width + letterSpacing;
169 if (run.length() - start > 0) {
170 components->append(TextRunComponent(run.characters16() + start, run.length() - start,
173 offset += components->last().m_width;
175 offset += letterSpacing;
178 for (int i = 0; i < run.length(); ++i) {
179 if (Font::treatAsSpace(run[i])) {
181 components->append(TextRunComponent(run.characters16() + start, i - start,
184 offset += components->last().m_width;
188 add = padding/numSpaces;
192 components->append(TextRunComponent(1, font, offset));
193 offset += add + components->last().m_width;
195 offset += wordSpacing;
199 if (run.length() - start > 0) {
200 components->append(TextRunComponent(run.characters16() + start, run.length() - start,
203 offset += components->last().m_width;
209 float Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
216 TextRunComponents components;
217 int w = generateComponents(&components, *this, run);
219 float widthOfDrawnText = 0;
221 for (int i = 0; i < (int)components.size(); ++i) {
222 const TextRunComponent& comp = components.at(i);
223 int len = comp.textLength();
224 int curEnd = curPos + len;
225 if (curPos < to && from < curEnd && !comp.isSpace()) {
226 FloatPoint pt = point;
228 pt.setX(point.x() + w - comp.m_offset - comp.m_width);
230 pt.setX(point.x() + comp.m_offset);
231 widthOfDrawnText += drawSimpleText(context, comp.m_textRun, pt, from - curPos, std::min(to, curEnd) - curPos);
237 return widthOfDrawnText;
240 void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
245 float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
247 TextRunComponents components;
248 int w = generateComponents(&components, *this, run);
252 int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, bool includePartialGlyphs) const
254 // FIXME: This truncation is not a problem for HTML, but only affects SVG, which passes floating-point numbers
255 // to Font::offsetForPosition(). Bug http://webkit.org/b/40673 tracks fixing this problem.
256 int position = static_cast<int>(xFloat);
258 TextRunComponents components;
259 int w = generateComponents(&components, *this, run);
266 for (size_t i = 0; i < components.size(); ++i) {
267 const TextRunComponent& comp = components.at(i);
268 int xe = w - comp.m_offset;
269 int xs = xe - comp.m_width;
271 return offset + (comp.isSpace()
272 ? static_cast<int>((position - xe) * comp.m_spaces / std::max(1.f, comp.m_width) + 0.5)
273 : offsetForPositionForSimpleText(comp.m_textRun, position - xs, includePartialGlyphs));
275 offset += comp.textLength();
278 for (size_t i = 0; i < components.size(); ++i) {
279 const TextRunComponent& comp = components.at(i);
280 int xs = comp.m_offset;
281 int xe = xs + comp.m_width;
282 if (position <= xe) {
283 if (position - xs >= xe)
284 return offset + comp.textLength();
285 return offset + (comp.isSpace()
286 ? static_cast<int>((position - xs) * comp.m_spaces / std::max(1.f, comp.m_width) + 0.5)
287 : offsetForPositionForSimpleText(comp.m_textRun, position - xs, includePartialGlyphs));
289 offset += comp.textLength();
296 static float cursorToX(const Font* font, const TextRunComponents& components, int width, bool rtl, int cursor)
299 for (size_t i = 0; i < components.size(); ++i) {
300 const TextRunComponent& comp = components.at(i);
301 if (start + comp.textLength() <= cursor) {
302 start += comp.textLength();
305 int xs = comp.m_offset;
307 xs = width - xs - comp.m_width;
309 int pos = cursor - start;
310 if (comp.isSpace()) {
312 pos = comp.textLength() - pos;
313 return xs + pos * comp.m_width / comp.m_spaces;
315 WidthIterator it(font, comp.m_textRun);
316 GlyphBuffer glyphBuffer;
317 it.advance(pos, &glyphBuffer);
318 return xs + it.m_runWidthSoFar;
323 FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& pt,
324 int h, int from, int to) const
326 TextRunComponents components;
327 int w = generateComponents(&components, *this, run);
329 if (!from && to == run.length())
330 return FloatRect(pt.x(), pt.y(), w, h);
332 float x1 = cursorToX(this, components, w, run.rtl(), from);
333 float x2 = cursorToX(this, components, w, run.rtl(), to);
337 return FloatRect(pt.x() + x1, pt.y(), x2 - x1, h);
340 bool Font::canReturnFallbackFontsForComplexText()
345 bool Font::canExpandAroundIdeographsInComplexText()
350 } // namespace WebCore