18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2007 Kevin Ollivier.  All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Font.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FontFallbackList.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "GlyphBuffer.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "GraphicsContext.h"
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "IntRect.h"
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "NotImplemented.h"
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SimpleFontData.h"
352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "TextRun.h"
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
378a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#if OS(WINDOWS)
388a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#include "UniscribeController.h"
395af96e2c7b73ebc627c6894727826a7576d31758Leon Clarketypedef WebCore::UniscribeController ComplexTextController;
4021939df44de1705786c545cd1bf519d47250322dBen Murdoch#endif
4121939df44de1705786c545cd1bf519d47250322dBen Murdoch
4221939df44de1705786c545cd1bf519d47250322dBen Murdoch#if OS(DARWIN)
4321939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "mac/ComplexTextController.h"
448a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#endif
458a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wx/dcclient.h>
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "fontprops.h"
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "non-kerned-drawing.h"
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianbool Font::canReturnFallbackFontsForComplexText()
535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
5421939df44de1705786c545cd1bf519d47250322dBen Murdoch#if OS(WINDOWS) || OS(DARWIN)
558a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    return true;
568a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#else
575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return false;
588a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#endif
595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
612fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockbool Font::canExpandAroundIdeographsInComplexText()
622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#if OS(DARWIN)
642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return true;
652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#else
662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return false;
672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#endif
682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font, const GlyphBuffer& glyphBuffer,
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                      int from, int numGlyphs, const FloatPoint& point) const
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // prepare DC
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Color color = graphicsContext->fillColor();
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // We can't use wx drawing methods on Win/Linux because they automatically kern text
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // so we've created a function with platform dependent drawing implementations that
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // will hopefully be folded into wx once the API has solidified.
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // see platform/wx/wxcode/<platform> for the implementations.
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    drawTextWithSpacing(graphicsContext, font, color, glyphBuffer, from, numGlyphs, point);
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian MonsenFloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8521939df44de1705786c545cd1bf519d47250322dBen Murdoch#if OS(WINDOWS) || OS(DARWIN)
8621939df44de1705786c545cd1bf519d47250322dBen Murdoch    ComplexTextController it(this, run);
878a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    it.advance(from);
888a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    float beforeWidth = it.runWidthSoFar();
898a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    it.advance(to);
908a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    float afterWidth = it.runWidthSoFar();
918a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
928a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning
938a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    if (run.rtl()) {
9421939df44de1705786c545cd1bf519d47250322dBen Murdoch#if OS(WINDOWS)
958a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        it.advance(run.length());
968a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        float totalWidth = it.runWidthSoFar();
978a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h);
9821939df44de1705786c545cd1bf519d47250322dBen Murdoch#else
9921939df44de1705786c545cd1bf519d47250322dBen Murdoch        float totalWidth = it.totalWidth();
10021939df44de1705786c545cd1bf519d47250322dBen Murdoch        return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h);
10121939df44de1705786c545cd1bf519d47250322dBen Murdoch#endif
1028a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    }
1038a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
1048a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);
1058a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#else
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    notImplemented();
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return FloatRect();
1088a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#endif
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
111f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochfloat Font::getGlyphsAndAdvancesForComplexText(const TextRun& /* run */, int /* from */, int /* to */, GlyphBuffer& /* glyphBuffer */, ForTextEmphasisOrNot /* forTextEmphasis */) const
112f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
113f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // FIXME: Implement this by moving most of the drawComplexText() implementation in here. Set up the
114f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // ComplexTextController according to forTextEmphasis.
115f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    notImplemented();
116f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return 0;
117f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
118f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
1198a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Blockvoid Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
12121939df44de1705786c545cd1bf519d47250322dBen Murdoch#if OS(WINDOWS) || OS(DARWIN)
1228a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    // This glyph buffer holds our glyphs + advances + font data for each glyph.
1238a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    GlyphBuffer glyphBuffer;
1248a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
1258a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    float startX = point.x();
12621939df44de1705786c545cd1bf519d47250322dBen Murdoch    ComplexTextController controller(this, run);
1278a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    controller.advance(from);
1288a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    float beforeWidth = controller.runWidthSoFar();
1298a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    controller.advance(to, &glyphBuffer);
1308a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
1318a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    // We couldn't generate any glyphs for the run.  Give up.
1328a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    if (glyphBuffer.isEmpty())
1338a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        return;
1348a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
1358a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    float afterWidth = controller.runWidthSoFar();
1368a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
1378a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    if (run.rtl()) {
13821939df44de1705786c545cd1bf519d47250322dBen Murdoch#if OS(WINDOWS)
1398a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        controller.advance(run.length());
1408a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        startX += controller.runWidthSoFar() - afterWidth;
14121939df44de1705786c545cd1bf519d47250322dBen Murdoch#else
14281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        startX += controller.totalWidth() - afterWidth;
14321939df44de1705786c545cd1bf519d47250322dBen Murdoch        for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end)
14421939df44de1705786c545cd1bf519d47250322dBen Murdoch            glyphBuffer.swap(i, end);
14521939df44de1705786c545cd1bf519d47250322dBen Murdoch#endif
1468a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    } else
1478a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        startX += beforeWidth;
1488a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
1498a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    // Draw the glyph buffer now at the starting point returned in startX.
1508a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    FloatPoint startPoint(startX, point.y());
151f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    drawGlyphBuffer(context, glyphBuffer, startPoint);
1528a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#else
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    notImplemented();
1548a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#endif
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
157f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid Font::drawEmphasisMarksForComplexText(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const
158f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
159f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    GlyphBuffer glyphBuffer;
160f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    float initialAdvance = getGlyphsAndAdvancesForComplexText(run, from, to, glyphBuffer, ForTextEmphasis);
161f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
162f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (glyphBuffer.isEmpty())
163f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return;
164f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
165f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    drawEmphasisMarks(context, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
166f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
1678a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
168dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockfloat Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow*) const
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
17021939df44de1705786c545cd1bf519d47250322dBen Murdoch#if OS(WINDOWS) || OS(DARWIN)
17121939df44de1705786c545cd1bf519d47250322dBen Murdoch    ComplexTextController controller(this, run, fallbackFonts);
1728a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#if OS(WINDOWS)
1738a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    controller.advance(run.length());
1748a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    return controller.runWidthSoFar();
1758a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#else
17621939df44de1705786c545cd1bf519d47250322dBen Murdoch    return controller.totalWidth();
17721939df44de1705786c545cd1bf519d47250322dBen Murdoch#endif
17821939df44de1705786c545cd1bf519d47250322dBen Murdoch#else
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    notImplemented();
1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
1818a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#endif
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
18406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenint Font::offsetForPositionForComplexText(const TextRun& run, float x, bool includePartialGlyphs) const
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
18621939df44de1705786c545cd1bf519d47250322dBen Murdoch#if OS(WINDOWS) || OS(DARWIN)
18721939df44de1705786c545cd1bf519d47250322dBen Murdoch    ComplexTextController controller(this, run);
1888a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    return controller.offsetForPosition(x, includePartialGlyphs);
1898a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#else
1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    notImplemented();
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
1928a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#endif
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
195