Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(217)

Side by Side Diff: Source/platform/fonts/Font.cpp

Issue 622033002: Merge FontHarfBuzz.cpp into Font.cpp (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/platform/blink_platform.gypi ('k') | Source/platform/fonts/harfbuzz/FontHarfBuzz.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2000 Dirk Mueller (mueller@kde.org) 4 * (C) 2000 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2003, 2006, 2010, 2011 Apple Inc. All rights reserved. 5 * Copyright (C) 2003, 2006, 2010, 2011 Apple Inc. All rights reserved.
6 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved.
6 * 7 *
7 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public 9 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version. 11 * version 2 of the License, or (at your option) any later version.
11 * 12 *
12 * This library is distributed in the hope that it will be useful, 13 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details. 16 * Library General Public License for more details.
16 * 17 *
17 * You should have received a copy of the GNU Library General Public License 18 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to 19 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA. 21 * Boston, MA 02110-1301, USA.
21 * 22 *
22 */ 23 */
23 24
24 #include "config.h" 25 #include "config.h"
25 #include "platform/fonts/Font.h" 26 #include "platform/fonts/Font.h"
26 27
28 #include "SkPaint.h"
29 #include "SkTemplates.h"
27 #include "platform/LayoutUnit.h" 30 #include "platform/LayoutUnit.h"
28 #include "platform/RuntimeEnabledFeatures.h" 31 #include "platform/RuntimeEnabledFeatures.h"
29 #include "platform/fonts/Character.h" 32 #include "platform/fonts/Character.h"
30 #include "platform/fonts/FontCache.h" 33 #include "platform/fonts/FontCache.h"
31 #include "platform/fonts/FontFallbackList.h" 34 #include "platform/fonts/FontFallbackList.h"
32 #include "platform/fonts/GlyphBuffer.h" 35 #include "platform/fonts/GlyphBuffer.h"
33 #include "platform/fonts/GlyphPageTreeNode.h" 36 #include "platform/fonts/GlyphPageTreeNode.h"
34 #include "platform/fonts/SimpleFontData.h" 37 #include "platform/fonts/SimpleFontData.h"
35 #include "platform/fonts/SimpleShaper.h" 38 #include "platform/fonts/SimpleShaper.h"
39 #include "platform/fonts/harfbuzz/HarfBuzzShaper.h"
36 #include "platform/geometry/FloatRect.h" 40 #include "platform/geometry/FloatRect.h"
37 #include "platform/graphics/GraphicsContext.h" 41 #include "platform/graphics/GraphicsContext.h"
38 #include "platform/text/TextRun.h" 42 #include "platform/text/TextRun.h"
39 #include "wtf/MainThread.h" 43 #include "wtf/MainThread.h"
40 #include "wtf/StdLibExtras.h" 44 #include "wtf/StdLibExtras.h"
41 #include "wtf/unicode/CharacterNames.h" 45 #include "wtf/unicode/CharacterNames.h"
42 #include "wtf/unicode/Unicode.h" 46 #include "wtf/unicode/Unicode.h"
43 47
44 using namespace WTF; 48 using namespace WTF;
45 using namespace Unicode; 49 using namespace Unicode;
46 50
47 namespace blink { 51 namespace blink {
48 52
49 CodePath Font::s_codePath = AutoPath; 53 CodePath Font::s_codePath = AutoPath;
50 54
51 // ============================================================================= ===============
52 // Font Implementation (Cross-Platform Portion)
53 // ============================================================================= ===============
54
55 Font::Font() 55 Font::Font()
56 { 56 {
57 } 57 }
58 58
59 Font::Font(const FontDescription& fd) 59 Font::Font(const FontDescription& fd)
60 : m_fontDescription(fd) 60 : m_fontDescription(fd)
61 { 61 {
62 } 62 }
63 63
64 Font::Font(const Font& other) 64 Font::Font(const Font& other)
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 if (glyphBuffer.isEmpty()) 230 if (glyphBuffer.isEmpty())
231 return nullptr; 231 return nullptr;
232 232
233 FloatRect blobBounds = runInfo.bounds; 233 FloatRect blobBounds = runInfo.bounds;
234 blobBounds.moveBy(-textOrigin); 234 blobBounds.moveBy(-textOrigin);
235 235
236 float ignoredWidth; 236 float ignoredWidth;
237 return buildTextBlob(glyphBuffer, initialAdvance, blobBounds, ignoredWidth, couldUseLCDRenderedText); 237 return buildTextBlob(glyphBuffer, initialAdvance, blobBounds, ignoredWidth, couldUseLCDRenderedText);
238 } 238 }
239 239
240 PassTextBlobPtr Font::buildTextBlob(const GlyphBuffer& glyphBuffer, float initia lAdvance,
241 const FloatRect& bounds, float& advance, bool couldUseLCD) const
242 {
243 ASSERT(RuntimeEnabledFeatures::textBlobEnabled());
244
245 // FIXME: Implement the more general full-positioning path.
246 ASSERT(!glyphBuffer.hasOffsets());
247
248 SkTextBlobBuilder builder;
249 SkScalar x = SkFloatToScalar(initialAdvance);
250 SkRect skBounds = bounds;
251
252 unsigned i = 0;
253 while (i < glyphBuffer.size()) {
254 const SimpleFontData* fontData = glyphBuffer.fontDataAt(i);
255
256 // FIXME: Handle vertical text.
257 if (fontData->platformData().orientation() == Vertical)
258 return nullptr;
259
260 // FIXME: Handle SVG fonts.
261 if (fontData->isSVGFont())
262 return nullptr;
263
264 // FIXME: FontPlatformData makes some decisions on the device scale
265 // factor, which is found via the GraphicsContext. This should be fixed
266 // to avoid correctness problems here.
267 SkPaint paint;
268 fontData->platformData().setupPaint(&paint);
269 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
270
271 // FIXME: this should go away after the big LCD cleanup.
272 paint.setLCDRenderText(paint.isLCDRenderText() && couldUseLCD);
273
274 unsigned start = i++;
275 while (i < glyphBuffer.size() && glyphBuffer.fontDataAt(i) == fontData)
276 i++;
277 unsigned count = i - start;
278
279 const SkTextBlobBuilder::RunBuffer& buffer = builder.allocRunPosH(paint, count, 0, &skBounds);
280
281 const uint16_t* glyphs = glyphBuffer.glyphs(start);
282 std::copy(glyphs, glyphs + count, buffer.glyphs);
283
284 const float* advances = glyphBuffer.advances(start);
285 for (unsigned j = 0; j < count; j++) {
286 buffer.pos[j] = x;
287 x += SkFloatToScalar(advances[j]);
288 }
289 }
290
291 advance = x;
292 return adoptRef(builder.build());
293 }
294
295
240 FloatRect Font::selectionRectForText(const TextRun& run, const FloatPoint& point , int h, int from, int to, bool accountForGlyphBounds) const 296 FloatRect Font::selectionRectForText(const TextRun& run, const FloatPoint& point , int h, int from, int to, bool accountForGlyphBounds) const
241 { 297 {
242 to = (to == -1 ? run.length() : to); 298 to = (to == -1 ? run.length() : to);
243 299
244 CodePath codePathToUse = codePath(run); 300 CodePath codePathToUse = codePath(run);
245 // FIXME: Use the fast code path once it handles partial runs with kerning a nd ligatures. See http://webkit.org/b/100050 301 // FIXME: Use the fast code path once it handles partial runs with kerning a nd ligatures. See http://webkit.org/b/100050
246 if (codePathToUse != ComplexPath && fontDescription().typesettingFeatures() && (from || to != run.length())) 302 if (codePathToUse != ComplexPath && fontDescription().typesettingFeatures() && (from || to != run.length()))
247 codePathToUse = ComplexPath; 303 codePathToUse = ComplexPath;
248 304
249 if (codePathToUse != ComplexPath) 305 if (codePathToUse != ComplexPath)
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after
722 { 778 {
723 GlyphBuffer glyphBuffer; 779 GlyphBuffer glyphBuffer;
724 float initialAdvance = getGlyphsAndAdvancesForSimpleText(runInfo, glyphBuffe r, ForTextEmphasis); 780 float initialAdvance = getGlyphsAndAdvancesForSimpleText(runInfo, glyphBuffe r, ForTextEmphasis);
725 781
726 if (glyphBuffer.isEmpty()) 782 if (glyphBuffer.isEmpty())
727 return; 783 return;
728 784
729 drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y())); 785 drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
730 } 786 }
731 787
732 float Font::drawGlyphBuffer(GraphicsContext* context, const TextRunPaintInfo& ru nInfo, const GlyphBuffer& glyphBuffer, const FloatPoint& point) const 788 static SkPaint textFillPaint(GraphicsContext* gc, const SimpleFontData* font)
789 {
790 SkPaint paint = gc->fillPaint();
791 font->platformData().setupPaint(&paint, gc);
792 gc->adjustTextRenderMode(&paint);
793 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
794 return paint;
795 }
796
797 static SkPaint textStrokePaint(GraphicsContext* gc, const SimpleFontData* font, bool isFilling)
798 {
799 SkPaint paint = gc->strokePaint();
800 font->platformData().setupPaint(&paint, gc);
801 gc->adjustTextRenderMode(&paint);
802 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
803 if (isFilling) {
804 // If there is a shadow and we filled above, there will already be
805 // a shadow. We don't want to draw it again or it will be too dark
806 // and it will go on top of the fill.
807 //
808 // Note that this isn't strictly correct, since the stroke could be
809 // very thick and the shadow wouldn't account for this. The "right"
810 // thing would be to draw to a new layer and then draw that layer
811 // with a shadow. But this is a lot of extra work for something
812 // that isn't normally an issue.
813 paint.setLooper(0);
814 }
815 return paint;
816 }
817
818 static void paintGlyphs(GraphicsContext* gc, const SimpleFontData* font,
819 const Glyph glyphs[], unsigned numGlyphs,
820 const SkPoint pos[], const FloatRect& textRect)
821 {
822 TextDrawingModeFlags textMode = gc->textDrawingMode();
823
824 // We draw text up to two times (once for fill, once for stroke).
825 if (textMode & TextModeFill) {
826 SkPaint paint = textFillPaint(gc, font);
827 gc->drawPosText(glyphs, numGlyphs * sizeof(Glyph), pos, textRect, paint) ;
828 }
829
830 if ((textMode & TextModeStroke) && gc->hasStroke()) {
831 SkPaint paint = textStrokePaint(gc, font, textMode & TextModeFill);
832 gc->drawPosText(glyphs, numGlyphs * sizeof(Glyph), pos, textRect, paint) ;
833 }
834 }
835
836 static void paintGlyphsHorizontal(GraphicsContext* gc, const SimpleFontData* fon t,
837 const Glyph glyphs[], unsigned numGlyphs,
838 const SkScalar xpos[], SkScalar constY, const FloatRect& textRect)
839 {
840 TextDrawingModeFlags textMode = gc->textDrawingMode();
841
842 if (textMode & TextModeFill) {
843 SkPaint paint = textFillPaint(gc, font);
844 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe ct, paint);
845 }
846
847 if ((textMode & TextModeStroke) && gc->hasStroke()) {
848 SkPaint paint = textStrokePaint(gc, font, textMode & TextModeFill);
849 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe ct, paint);
850 }
851 }
852
853 void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
854 const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs,
855 const FloatPoint& point, const FloatRect& textRect) const
856 {
857 SkScalar x = SkFloatToScalar(point.x());
858 SkScalar y = SkFloatToScalar(point.y());
859
860 const OpenTypeVerticalData* verticalData = font->verticalData();
861 if (font->platformData().orientation() == Vertical && verticalData) {
862 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs);
863 SkPoint* pos = storage.get();
864
865 AffineTransform savedMatrix = gc->getCTM();
866 gc->concatCTM(AffineTransform(0, -1, 1, 0, point.x(), point.y()));
867 gc->concatCTM(AffineTransform(1, 0, 0, 1, -point.x(), -point.y()));
868
869 const unsigned kMaxBufferLength = 256;
870 Vector<FloatPoint, kMaxBufferLength> translations;
871
872 const FontMetrics& metrics = font->fontMetrics();
873 SkScalar verticalOriginX = SkFloatToScalar(point.x() + metrics.floatAsce nt() - metrics.floatAscent(IdeographicBaseline));
874 float horizontalOffset = point.x();
875
876 unsigned glyphIndex = 0;
877 while (glyphIndex < numGlyphs) {
878 unsigned chunkLength = std::min(kMaxBufferLength, numGlyphs - glyphI ndex);
879
880 const Glyph* glyphs = glyphBuffer.glyphs(from + glyphIndex);
881 translations.resize(chunkLength);
882 verticalData->getVerticalTranslationsForGlyphs(font, &glyphs[0], chu nkLength, reinterpret_cast<float*>(&translations[0]));
883
884 x = verticalOriginX;
885 y = SkFloatToScalar(point.y() + horizontalOffset - point.x());
886
887 float currentWidth = 0;
888 for (unsigned i = 0; i < chunkLength; ++i, ++glyphIndex) {
889 pos[i].set(
890 x + SkIntToScalar(lroundf(translations[i].x())),
891 y + -SkIntToScalar(-lroundf(currentWidth - translations[i].y ())));
892 currentWidth += glyphBuffer.advanceAt(from + glyphIndex);
893 }
894 horizontalOffset += currentWidth;
895 paintGlyphs(gc, font, glyphs, chunkLength, pos, textRect);
896 }
897
898 gc->setCTM(savedMatrix);
899 return;
900 }
901
902 if (!glyphBuffer.hasOffsets()) {
903 SkAutoSTMalloc<64, SkScalar> storage(numGlyphs);
904 SkScalar* xpos = storage.get();
905 const float* adv = glyphBuffer.advances(from);
906 for (unsigned i = 0; i < numGlyphs; i++) {
907 xpos[i] = x;
908 x += SkFloatToScalar(adv[i]);
909 }
910 const Glyph* glyphs = glyphBuffer.glyphs(from);
911 paintGlyphsHorizontal(gc, font, glyphs, numGlyphs, xpos, SkFloatToScalar (y), textRect);
912 return;
913 }
914
915 ASSERT(glyphBuffer.hasOffsets());
916 const GlyphBufferWithOffsets& glyphBufferWithOffsets =
917 static_cast<const GlyphBufferWithOffsets&>(glyphBuffer);
918 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs);
919 SkPoint* pos = storage.get();
920 const FloatSize* offsets = glyphBufferWithOffsets.offsets(from);
921 const float* advances = glyphBufferWithOffsets.advances(from);
922 SkScalar advanceSoFar = SkFloatToScalar(0);
923 for (unsigned i = 0; i < numGlyphs; i++) {
924 pos[i].set(
925 x + SkFloatToScalar(offsets[i].width()) + advanceSoFar,
926 y + SkFloatToScalar(offsets[i].height()));
927 advanceSoFar += SkFloatToScalar(advances[i]);
928 }
929
930 const Glyph* glyphs = glyphBufferWithOffsets.glyphs(from);
931 paintGlyphs(gc, font, glyphs, numGlyphs, pos, textRect);
932 }
933
934 void Font::drawTextBlob(GraphicsContext* gc, const SkTextBlob* blob, const SkPoi nt& origin) const
935 {
936 ASSERT(RuntimeEnabledFeatures::textBlobEnabled());
937
938 // FIXME: It would be good to move this to Font.cpp, if we're sure that none
939 // of the things in FontMac's setupPaint need to apply here.
940 // See also paintGlyphs.
941 TextDrawingModeFlags textMode = gc->textDrawingMode();
942
943 if (textMode & TextModeFill)
944 gc->drawTextBlob(blob, origin, gc->fillPaint());
945
946 if ((textMode & TextModeStroke) && gc->hasStroke()) {
947 SkPaint paint = gc->strokePaint();
948 if (textMode & TextModeFill)
949 paint.setLooper(0);
950 gc->drawTextBlob(blob, origin, paint);
951 }
952 }
953
954 float Font::drawComplexText(GraphicsContext* gc, const TextRunPaintInfo& runInfo , const FloatPoint& point) const
955 {
956 if (!runInfo.run.length())
957 return 0;
958
959 TextDrawingModeFlags textMode = gc->textDrawingMode();
960 bool fill = textMode & TextModeFill;
961 bool stroke = (textMode & TextModeStroke) && gc->hasStroke();
962
963 if (!fill && !stroke)
964 return 0;
965
966 GlyphBufferWithOffsets glyphBuffer;
967 HarfBuzzShaper shaper(this, runInfo.run);
968 shaper.setDrawRange(runInfo.from, runInfo.to);
969 if (!shaper.shape(&glyphBuffer) || glyphBuffer.isEmpty())
970 return 0;
971 return drawGlyphBuffer(gc, runInfo, glyphBuffer, point);
972 }
973
974 void Font::drawEmphasisMarksForComplexText(GraphicsContext* context, const TextR unPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const
975 {
976 GlyphBuffer glyphBuffer;
977
978 float initialAdvance = getGlyphsAndAdvancesForComplexText(runInfo, glyphBuff er, ForTextEmphasis);
979
980 if (glyphBuffer.isEmpty())
981 return;
982
983 drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
984 }
985
986 float Font::getGlyphsAndAdvancesForComplexText(const TextRunPaintInfo& runInfo, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
987 {
988 HarfBuzzShaper shaper(this, runInfo.run, HarfBuzzShaper::ForTextEmphasis);
989 shaper.setDrawRange(runInfo.from, runInfo.to);
990 shaper.shape(&glyphBuffer);
991 return 0;
992 }
993
994 float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon tData*>* fallbackFonts, IntRectExtent* glyphBounds) const
995 {
996 HarfBuzzShaper shaper(this, run, HarfBuzzShaper::NotForTextEmphasis, fallbac kFonts);
997 if (!shaper.shape())
998 return 0;
999
1000 glyphBounds->setTop(floorf(-shaper.glyphBoundingBox().top()));
1001 glyphBounds->setBottom(ceilf(shaper.glyphBoundingBox().bottom()));
1002 glyphBounds->setLeft(std::max<int>(0, floorf(-shaper.glyphBoundingBox().left ())));
1003 glyphBounds->setRight(std::max<int>(0, ceilf(shaper.glyphBoundingBox().right () - shaper.totalWidth())));
1004
1005 return shaper.totalWidth();
1006 }
1007
1008 // Return the code point index for the given |x| offset into the text run.
1009 int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat,
1010 bool includePartialGlyphs) const
1011 {
1012 HarfBuzzShaper shaper(this, run);
1013 if (!shaper.shape())
1014 return 0;
1015 return shaper.offsetForPosition(xFloat);
1016 }
1017
1018 // Return the rectangle for selecting the given range of code-points in the Text Run.
1019 FloatRect Font::selectionRectForComplexText(const TextRun& run,
1020 const FloatPoint& point, int height, int from, int to) const
1021 {
1022 HarfBuzzShaper shaper(this, run);
1023 if (!shaper.shape())
1024 return FloatRect();
1025 return shaper.selectionRect(point, height, from, to);
1026 }
1027
1028 float Font::drawGlyphBuffer(GraphicsContext* context,
1029 const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer,
1030 const FloatPoint& point) const
733 { 1031 {
734 // Draw each contiguous run of glyphs that use the same font data. 1032 // Draw each contiguous run of glyphs that use the same font data.
735 const SimpleFontData* fontData = glyphBuffer.fontDataAt(0); 1033 const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
736 FloatPoint startPoint(point); 1034 FloatPoint startPoint(point);
737 float advanceSoFar = 0; 1035 float advanceSoFar = 0;
738 unsigned lastFrom = 0; 1036 unsigned lastFrom = 0;
739 unsigned nextGlyph = 0; 1037 unsigned nextGlyph = 0;
740 #if ENABLE(SVG_FONTS) 1038 #if ENABLE(SVG_FONTS)
741 TextRun::RenderingContext* renderingContext = runInfo.run.renderingContext() ; 1039 TextRun::RenderingContext* renderingContext = runInfo.run.renderingContext() ;
742 #endif 1040 #endif
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
901 if (delta <= 0) 1199 if (delta <= 0)
902 break; 1200 break;
903 } 1201 }
904 } 1202 }
905 } 1203 }
906 1204
907 return offset; 1205 return offset;
908 } 1206 }
909 1207
910 } // namespace blink 1208 } // namespace blink
OLDNEW
« no previous file with comments | « Source/platform/blink_platform.gypi ('k') | Source/platform/fonts/harfbuzz/FontHarfBuzz.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698