OLD | NEW |
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 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved. |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 CodePath Font::codePath(const TextRunPaintInfo& runInfo) const | 336 CodePath Font::codePath(const TextRunPaintInfo& runInfo) const |
337 { | 337 { |
338 const TextRun& run = runInfo.run; | 338 const TextRun& run = runInfo.run; |
339 | 339 |
340 if (fontDescription().typesettingFeatures() && (runInfo.from || runInfo.to !
= run.length())) | 340 if (fontDescription().typesettingFeatures() && (runInfo.from || runInfo.to !
= run.length())) |
341 return ComplexPath; | 341 return ComplexPath; |
342 | 342 |
343 if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings
()->size() > 0 && m_fontDescription.letterSpacing() == 0) | 343 if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings
()->size() > 0 && m_fontDescription.letterSpacing() == 0) |
344 return ComplexPath; | 344 return ComplexPath; |
345 | 345 |
| 346 if (m_fontDescription.orientation() == Vertical) |
| 347 return ComplexPath; |
| 348 |
346 if (m_fontDescription.widthVariant() != RegularWidth) | 349 if (m_fontDescription.widthVariant() != RegularWidth) |
347 return ComplexPath; | 350 return ComplexPath; |
348 | 351 |
349 if (run.length() > 1 && fontDescription().typesettingFeatures()) | 352 if (run.length() > 1 && fontDescription().typesettingFeatures()) |
350 return ComplexPath; | 353 return ComplexPath; |
351 | 354 |
352 // FIXME: This really shouldn't be needed but for some reason the | 355 // FIXME: This really shouldn't be needed but for some reason the |
353 // TextRendering setting doesn't propagate to typesettingFeatures in time | 356 // TextRendering setting doesn't propagate to typesettingFeatures in time |
354 // for the prefs width calculation. | 357 // for the prefs width calculation. |
355 if (fontDescription().textRendering() == OptimizeLegibility || fontDescripti
on().textRendering() == GeometricPrecision) | 358 if (fontDescription().textRendering() == OptimizeLegibility || fontDescripti
on().textRendering() == GeometricPrecision) |
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
698 SkPaint paint = textFillPaint(gc, font); | 701 SkPaint paint = textFillPaint(gc, font); |
699 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe
ct, paint); | 702 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe
ct, paint); |
700 } | 703 } |
701 | 704 |
702 if ((textMode & TextModeStroke) && gc->hasStroke()) { | 705 if ((textMode & TextModeStroke) && gc->hasStroke()) { |
703 SkPaint paint = textStrokePaint(gc, font, textMode & TextModeFill); | 706 SkPaint paint = textStrokePaint(gc, font, textMode & TextModeFill); |
704 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe
ct, paint); | 707 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe
ct, paint); |
705 } | 708 } |
706 } | 709 } |
707 | 710 |
708 void Font::paintGlyphsVertical(GraphicsContext* gc, const SimpleFontData* font, | |
709 const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs, const Flo
atPoint& point, | |
710 const FloatRect& textRect) const | |
711 { | |
712 const OpenTypeVerticalData* verticalData = font->verticalData(); | |
713 | |
714 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs); | |
715 SkPoint* pos = storage.get(); | |
716 | |
717 // Bend over backwards to preserve legacy rounding. | |
718 float initialAdvance = glyphBuffer.xOffsetAt(from); | |
719 FloatPoint adjustedPoint(point.x() + initialAdvance, point.y()); | |
720 | |
721 GraphicsContextStateSaver stateSaver(*gc); | |
722 gc->concatCTM(AffineTransform(0, -1, 1, 0, adjustedPoint.x(), adjustedPoint.
y())); | |
723 gc->concatCTM(AffineTransform(1, 0, 0, 1, -adjustedPoint.x(), -adjustedPoint
.y())); | |
724 | |
725 const unsigned kMaxBufferLength = 256; | |
726 Vector<FloatPoint, kMaxBufferLength> translations; | |
727 | |
728 const FontMetrics& metrics = font->fontMetrics(); | |
729 float verticalOriginX = adjustedPoint.x() + metrics.floatAscent() - metrics.
floatAscent(IdeographicBaseline); | |
730 | |
731 unsigned glyphIndex = 0; | |
732 while (glyphIndex < numGlyphs) { | |
733 unsigned chunkLength = std::min(kMaxBufferLength, numGlyphs - glyphIndex
); | |
734 | |
735 const Glyph* glyphs = glyphBuffer.glyphs(from + glyphIndex); | |
736 | |
737 translations.resize(chunkLength); | |
738 verticalData->getVerticalTranslationsForGlyphs(font, glyphs, chunkLength
, | |
739 reinterpret_cast<float*>(&translations[0])); | |
740 | |
741 for (unsigned i = 0; i < chunkLength; ++i, ++glyphIndex) { | |
742 SkScalar x = verticalOriginX + lroundf(translations[i].x()); | |
743 SkScalar y = adjustedPoint.y() - SkIntToScalar( | |
744 -lroundf(glyphBuffer.xOffsetAt(from + glyphIndex) - initialAdvan
ce - translations[i].y())); | |
745 pos[i].set(x, y); | |
746 } | |
747 paintGlyphs(gc, font, glyphs, chunkLength, pos, textRect); | |
748 } | |
749 } | |
750 | |
751 void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, | 711 void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, |
752 const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs, | 712 const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs, |
753 const FloatPoint& point, const FloatRect& textRect) const | 713 const FloatPoint& point, const FloatRect& textRect) const |
754 { | 714 { |
755 ASSERT(glyphBuffer.size() >= from + numGlyphs); | 715 ASSERT(glyphBuffer.size() >= from + numGlyphs); |
756 | 716 |
757 if (font->platformData().orientation() == Vertical && font->verticalData())
{ | |
758 paintGlyphsVertical(gc, font, glyphBuffer, from, numGlyphs, point, textR
ect); | |
759 return; | |
760 } | |
761 | |
762 if (!glyphBuffer.hasVerticalOffsets()) { | 717 if (!glyphBuffer.hasVerticalOffsets()) { |
763 SkAutoSTMalloc<64, SkScalar> storage(numGlyphs); | 718 SkAutoSTMalloc<64, SkScalar> storage(numGlyphs); |
764 SkScalar* xpos = storage.get(); | 719 SkScalar* xpos = storage.get(); |
765 for (unsigned i = 0; i < numGlyphs; i++) | 720 for (unsigned i = 0; i < numGlyphs; i++) |
766 xpos[i] = SkFloatToScalar(point.x() + glyphBuffer.xOffsetAt(from + i
)); | 721 xpos[i] = SkFloatToScalar(point.x() + glyphBuffer.xOffsetAt(from + i
)); |
767 | 722 |
768 paintGlyphsHorizontal(gc, font, glyphBuffer.glyphs(from), numGlyphs, xpo
s, | 723 paintGlyphsHorizontal(gc, font, glyphBuffer.glyphs(from), numGlyphs, xpo
s, |
769 SkFloatToScalar(point.y()), textRect); | 724 SkFloatToScalar(point.y()), textRect); |
770 return; | 725 return; |
771 } | 726 } |
772 | 727 |
| 728 bool drawVertically = font->platformData().orientation() == Vertical && font
->verticalData(); |
| 729 |
| 730 GraphicsContextStateSaver stateSaver(*gc, false); |
| 731 if (drawVertically) { |
| 732 stateSaver.save(); |
| 733 gc->concatCTM(AffineTransform(0, -1, 1, 0, point.x(), point.y())); |
| 734 gc->concatCTM(AffineTransform(1, 0, 0, 1, -point.x(), -point.y())); |
| 735 } |
| 736 |
| 737 const float verticalBaselineXOffset = drawVertically ? SkFloatToScalar(font-
>fontMetrics().floatAscent() - font->fontMetrics().floatAscent(IdeographicBaseli
ne)) : 0; |
| 738 |
773 ASSERT(glyphBuffer.hasVerticalOffsets()); | 739 ASSERT(glyphBuffer.hasVerticalOffsets()); |
774 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs); | 740 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs); |
775 SkPoint* pos = storage.get(); | 741 SkPoint* pos = storage.get(); |
776 for (unsigned i = 0; i < numGlyphs; i++) { | 742 for (unsigned i = 0; i < numGlyphs; i++) { |
777 pos[i].set( | 743 pos[i].set( |
778 SkFloatToScalar(point.x() + glyphBuffer.xOffsetAt(from + i)), | 744 SkFloatToScalar(point.x() + verticalBaselineXOffset + glyphBuffer.xO
ffsetAt(from + i)), |
779 SkFloatToScalar(point.y() + glyphBuffer.yOffsetAt(from + i))); | 745 SkFloatToScalar(point.y() + glyphBuffer.yOffsetAt(from + i))); |
780 } | 746 } |
781 | 747 |
782 paintGlyphs(gc, font, glyphBuffer.glyphs(from), numGlyphs, pos, textRect); | 748 paintGlyphs(gc, font, glyphBuffer.glyphs(from), numGlyphs, pos, textRect); |
783 } | 749 } |
784 | 750 |
785 void Font::drawTextBlob(GraphicsContext* gc, const SkTextBlob* blob, const SkPoi
nt& origin) const | 751 void Font::drawTextBlob(GraphicsContext* gc, const SkTextBlob* blob, const SkPoi
nt& origin) const |
786 { | 752 { |
787 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); | 753 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); |
788 | 754 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
829 HarfBuzzShaper shaper(this, run); | 795 HarfBuzzShaper shaper(this, run); |
830 if (!shaper.shape()) | 796 if (!shaper.shape()) |
831 return FloatRect(); | 797 return FloatRect(); |
832 return shaper.selectionRect(point, height, from, to); | 798 return shaper.selectionRect(point, height, from, to); |
833 } | 799 } |
834 | 800 |
835 void Font::drawGlyphBuffer(GraphicsContext* context, | 801 void Font::drawGlyphBuffer(GraphicsContext* context, |
836 const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, | 802 const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, |
837 const FloatPoint& point) const | 803 const FloatPoint& point) const |
838 { | 804 { |
| 805 if (!glyphBuffer.size()) |
| 806 return; |
| 807 |
839 // Draw each contiguous run of glyphs that use the same font data. | 808 // Draw each contiguous run of glyphs that use the same font data. |
840 const SimpleFontData* fontData = glyphBuffer.fontDataAt(0); | 809 const SimpleFontData* fontData = glyphBuffer.fontDataAt(0); |
841 unsigned lastFrom = 0; | 810 unsigned lastFrom = 0; |
842 unsigned nextGlyph; | 811 unsigned nextGlyph; |
843 | 812 |
844 for (nextGlyph = 0; nextGlyph < glyphBuffer.size(); ++nextGlyph) { | 813 for (nextGlyph = 0; nextGlyph < glyphBuffer.size(); ++nextGlyph) { |
845 const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph); | 814 const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph); |
846 | 815 |
847 if (nextFontData != fontData) { | 816 if (nextFontData != fontData) { |
848 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - las
tFrom, point, | 817 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - las
tFrom, point, |
849 runInfo.bounds); | 818 runInfo.bounds); |
850 | 819 |
851 lastFrom = nextGlyph; | 820 lastFrom = nextGlyph; |
852 fontData = nextFontData; | 821 fontData = nextFontData; |
853 } | 822 } |
854 } | 823 } |
855 | 824 |
856 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, p
oint, | 825 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, p
oint, |
857 runInfo.bounds); | 826 runInfo.bounds); |
858 } | 827 } |
859 | 828 |
860 inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph
glyph) | 829 inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph
glyph, FontOrientation orientation = Horizontal) |
861 { | 830 { |
862 if (fontData->platformData().orientation() == Horizontal) { | 831 FloatRect bounds = fontData->boundsForGlyph(glyph); |
863 FloatRect bounds = fontData->boundsForGlyph(glyph); | 832 if (orientation == Horizontal) |
864 return bounds.x() + bounds.width() / 2; | 833 return bounds.x() + bounds.width() / 2; |
865 } | 834 return bounds.y() + bounds.height() / 2; |
866 // FIXME: Use glyph bounds once they make sense for vertical fonts. | |
867 return fontData->widthForGlyph(glyph) / 2; | |
868 } | 835 } |
869 | 836 |
870 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r
unInfo, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoi
nt& point) const | 837 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r
unInfo, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoi
nt& point) const |
871 { | 838 { |
872 FontCachePurgePreventer purgePreventer; | 839 FontCachePurgePreventer purgePreventer; |
873 | 840 |
874 GlyphData markGlyphData; | 841 GlyphData markGlyphData; |
875 if (!getEmphasisMarkGlyphData(mark, markGlyphData)) | 842 if (!getEmphasisMarkGlyphData(mark, markGlyphData)) |
876 return; | 843 return; |
877 | 844 |
878 const SimpleFontData* markFontData = markGlyphData.fontData; | 845 const SimpleFontData* markFontData = markGlyphData.fontData; |
879 ASSERT(markFontData); | 846 ASSERT(markFontData); |
880 if (!markFontData) | 847 if (!markFontData) |
881 return; | 848 return; |
882 | 849 |
883 GlyphBuffer markBuffer; | 850 GlyphBuffer markBuffer; |
884 float midMarkOffset = offsetToMiddleOfGlyph(markFontData, markGlyphData.glyp
h); | 851 bool drawVertically = markFontData->platformData().orientation() == Vertical
&& markFontData->verticalData(); |
885 for (unsigned i = 0; i < glyphBuffer.size(); ++i) { | 852 for (unsigned i = 0; i < glyphBuffer.size(); ++i) { |
886 // Skip marks for suppressed glyphs. | 853 // Skip marks for suppressed glyphs. |
887 if (!glyphBuffer.glyphAt(i)) | 854 if (!glyphBuffer.glyphAt(i)) |
888 continue; | 855 continue; |
889 | 856 |
890 // We want the middle of the emphasis mark aligned with the middle of th
e glyph. | 857 // We want the middle of the emphasis mark aligned with the middle of th
e glyph. |
891 // The input offsets are already adjusted to point to the middle of the
glyph, so all | 858 // The input offsets are already adjusted to point to the middle of the
glyph, so all |
892 // is left to do is adjust for 1/2 mark width. | 859 // is left to do is adjust for 1/2 mark width. |
893 // FIXME: we could avoid this by passing some additional info to the sha
per, | 860 // FIXME: we could avoid this by passing some additional info to the sha
per, |
894 // and perform all adjustments at buffer build time. | 861 // and perform all adjustments at buffer build time. |
895 markBuffer.add(markGlyphData.glyph, markFontData, glyphBuffer.xOffsetAt(
i) - midMarkOffset); | 862 if (!drawVertically) { |
| 863 markBuffer.add(markGlyphData.glyph, markFontData, glyphBuffer.xOffse
tAt(i) - offsetToMiddleOfGlyph(markFontData, markGlyphData.glyph)); |
| 864 } else { |
| 865 markBuffer.add(markGlyphData.glyph, markFontData, FloatPoint(- offse
tToMiddleOfGlyph(markFontData, markGlyphData.glyph), |
| 866 glyphBuffer.xOffsetAt(i) - offsetToMiddleOfGlyph(markFontData, m
arkGlyphData.glyph, Vertical))); |
| 867 } |
896 } | 868 } |
897 | 869 |
898 drawGlyphBuffer(context, runInfo, markBuffer, point); | 870 drawGlyphBuffer(context, runInfo, markBuffer, point); |
899 } | 871 } |
900 | 872 |
901 float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFont
Data*>* fallbackFonts, IntRectExtent* glyphBounds) const | 873 float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFont
Data*>* fallbackFonts, IntRectExtent* glyphBounds) const |
902 { | 874 { |
903 SimpleShaper::GlyphBounds bounds; | 875 SimpleShaper::GlyphBounds bounds; |
904 SimpleShaper shaper(this, run, fallbackFonts, glyphBounds ? &bounds : 0); | 876 SimpleShaper shaper(this, run, fallbackFonts, glyphBounds ? &bounds : 0); |
905 shaper.advance(run.length()); | 877 shaper.advance(run.length()); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
974 if (delta <= 0) | 946 if (delta <= 0) |
975 break; | 947 break; |
976 } | 948 } |
977 } | 949 } |
978 } | 950 } |
979 | 951 |
980 return offset; | 952 return offset; |
981 } | 953 } |
982 | 954 |
983 } // namespace blink | 955 } // namespace blink |
OLD | NEW |