2 * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "ComplexTextController.h"
29 #include "FontGlyphs.h"
30 #include "GlyphBuffer.h"
31 #include "GraphicsContext.h"
33 #include "LayoutRect.h"
34 #include "SimpleFontData.h"
36 #include <wtf/MathExtras.h>
40 void Font::adjustSelectionRectForComplexText(const TextRun& run, LayoutRect& selectionRect, unsigned from, unsigned to) const
42 ComplexTextController controller(this, run);
43 controller.advance(from);
44 float beforeWidth = controller.runWidthSoFar();
45 controller.advance(to);
46 float afterWidth = controller.runWidthSoFar();
49 selectionRect.move(controller.totalWidth() - afterWidth, 0);
51 selectionRect.move(beforeWidth, 0);
52 selectionRect.setWidth(afterWidth - beforeWidth);
55 float Font::getGlyphsAndAdvancesForComplexText(const TextRun& run, unsigned from, unsigned to, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
59 ComplexTextController controller(this, run, false, 0, forTextEmphasis);
60 controller.advance(from);
61 float beforeWidth = controller.runWidthSoFar();
62 controller.advance(to, &glyphBuffer);
64 if (glyphBuffer.isEmpty())
67 float afterWidth = controller.runWidthSoFar();
70 initialAdvance = controller.totalWidth() + controller.finalRoundingWidth() - afterWidth;
71 glyphBuffer.reverse(0, glyphBuffer.size());
73 initialAdvance = beforeWidth;
75 return initialAdvance;
78 float Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, unsigned from, unsigned to) const
80 // This glyph buffer holds our glyphs + advances + font data for each glyph.
81 GlyphBuffer glyphBuffer;
83 float startX = point.x() + getGlyphsAndAdvancesForComplexText(run, from, to, glyphBuffer);
85 // We couldn't generate any glyphs for the run. Give up.
86 if (glyphBuffer.isEmpty())
89 // Draw the glyph buffer now at the starting point returned in startX.
90 FloatPoint startPoint(startX, point.y());
91 drawGlyphBuffer(context, run, glyphBuffer, startPoint);
93 return startPoint.x() - startX;
96 void Font::drawEmphasisMarksForComplexText(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, unsigned from, unsigned to) const
98 GlyphBuffer glyphBuffer;
99 float initialAdvance = getGlyphsAndAdvancesForComplexText(run, from, to, glyphBuffer, ForTextEmphasis);
101 if (glyphBuffer.isEmpty())
104 drawEmphasisMarks(context, run, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
107 float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
109 ComplexTextController controller(this, run, true, fallbackFonts);
111 glyphOverflow->top = std::max<int>(glyphOverflow->top, ceilf(-controller.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent()));
112 glyphOverflow->bottom = std::max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().descent()));
113 glyphOverflow->left = std::max<int>(0, ceilf(-controller.minGlyphBoundingBoxX()));
114 glyphOverflow->right = std::max<int>(0, ceilf(controller.maxGlyphBoundingBoxX() - controller.totalWidth()));
116 return controller.totalWidth();
119 int Font::offsetForPositionForComplexText(const TextRun& run, float x, bool includePartialGlyphs) const
121 ComplexTextController controller(this, run);
122 return controller.offsetForPosition(x, includePartialGlyphs);
125 const SimpleFontData* Font::fontDataForCombiningCharacterSequence(const UChar* characters, size_t length, FontDataVariant variant) const
127 UChar32 baseCharacter;
128 size_t baseCharacterLength = 0;
129 U16_NEXT(characters, baseCharacterLength, length, baseCharacter);
131 GlyphData baseCharacterGlyphData = glyphDataForCharacter(baseCharacter, false, variant);
133 if (!baseCharacterGlyphData.glyph)
136 if (length == baseCharacterLength)
137 return baseCharacterGlyphData.fontData;
139 bool triedBaseCharacterFontData = false;
142 for (const FontData* fontData = fontDataAt(0); fontData; fontData = fontDataAt(++i)) {
143 const SimpleFontData* simpleFontData = fontData->fontDataForCharacter(baseCharacter);
145 if (baseCharacter >= 0x0600 && baseCharacter <= 0x06ff && simpleFontData->shouldNotBeUsedForArabic())
148 if (variant == NormalVariant) {
149 if (simpleFontData->platformData().orientation() == Vertical) {
150 if (isCJKIdeographOrSymbol(baseCharacter) && !simpleFontData->hasVerticalGlyphs()) {
151 variant = BrokenIdeographVariant;
152 simpleFontData = simpleFontData->brokenIdeographFontData().get();
153 } else if (m_fontDescription.nonCJKGlyphOrientation() == NonCJKGlyphOrientationVerticalRight) {
154 SimpleFontData* verticalRightFontData = simpleFontData->verticalRightOrientationFontData().get();
155 Glyph verticalRightGlyph = verticalRightFontData->glyphForCharacter(baseCharacter);
156 if (verticalRightGlyph == baseCharacterGlyphData.glyph)
157 simpleFontData = verticalRightFontData;
159 SimpleFontData* uprightFontData = simpleFontData->uprightOrientationFontData().get();
160 Glyph uprightGlyph = uprightFontData->glyphForCharacter(baseCharacter);
161 if (uprightGlyph != baseCharacterGlyphData.glyph)
162 simpleFontData = uprightFontData;
166 if (const SimpleFontData* variantFontData = simpleFontData->variantFontData(m_fontDescription, variant).get())
167 simpleFontData = variantFontData;
170 if (simpleFontData == baseCharacterGlyphData.fontData)
171 triedBaseCharacterFontData = true;
173 if (simpleFontData->canRenderCombiningCharacterSequence(characters, length))
174 return simpleFontData;
177 if (!triedBaseCharacterFontData && baseCharacterGlyphData.fontData && baseCharacterGlyphData.fontData->canRenderCombiningCharacterSequence(characters, length))
178 return baseCharacterGlyphData.fontData;
180 return SimpleFontData::systemFallback();
183 } // namespace WebCore