1a033630e805c407080221e20b236b6054f324670Raph Levien/*
2a033630e805c407080221e20b236b6054f324670Raph Levien * Copyright (C) 2013 The Android Open Source Project
3a033630e805c407080221e20b236b6054f324670Raph Levien *
4a033630e805c407080221e20b236b6054f324670Raph Levien * Licensed under the Apache License, Version 2.0 (the "License");
5a033630e805c407080221e20b236b6054f324670Raph Levien * you may not use this file except in compliance with the License.
6a033630e805c407080221e20b236b6054f324670Raph Levien * You may obtain a copy of the License at
7a033630e805c407080221e20b236b6054f324670Raph Levien *
8a033630e805c407080221e20b236b6054f324670Raph Levien *      http://www.apache.org/licenses/LICENSE-2.0
9a033630e805c407080221e20b236b6054f324670Raph Levien *
10a033630e805c407080221e20b236b6054f324670Raph Levien * Unless required by applicable law or agreed to in writing, software
11a033630e805c407080221e20b236b6054f324670Raph Levien * distributed under the License is distributed on an "AS IS" BASIS,
12a033630e805c407080221e20b236b6054f324670Raph Levien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a033630e805c407080221e20b236b6054f324670Raph Levien * See the License for the specific language governing permissions and
14a033630e805c407080221e20b236b6054f324670Raph Levien * limitations under the License.
15a033630e805c407080221e20b236b6054f324670Raph Levien */
16a033630e805c407080221e20b236b6054f324670Raph Levien
17dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include "MinikinSkia.h"
18afbd0f1fef46ef0ddf633dfde0de724db3da1405Sergei Vasilinetc
19dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <SkPaint.h>
20dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <SkTypeface.h>
21a033630e805c407080221e20b236b6054f324670Raph Levien#include <cutils/log.h>
22a033630e805c407080221e20b236b6054f324670Raph Levien
23a033630e805c407080221e20b236b6054f324670Raph Leviennamespace android {
24a033630e805c407080221e20b236b6054f324670Raph Levien
25296bf8c55aaba0025f3e5b904fda3b6e15686753Raph LevienMinikinFontSkia::MinikinFontSkia(SkTypeface* typeface, const void* fontData, size_t fontSize,
26296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien        int ttcIndex) :
27b93872ad64afaafa1799a293850f48a96708182eSeigo Nonaka    MinikinFont(typeface->uniqueID()), mTypeface(typeface), mFontData(fontData),
28b93872ad64afaafa1799a293850f48a96708182eSeigo Nonaka    mFontSize(fontSize), mTtcIndex(ttcIndex) {
29a033630e805c407080221e20b236b6054f324670Raph Levien}
30a033630e805c407080221e20b236b6054f324670Raph Levien
31a033630e805c407080221e20b236b6054f324670Raph LevienMinikinFontSkia::~MinikinFontSkia() {
32a033630e805c407080221e20b236b6054f324670Raph Levien    SkSafeUnref(mTypeface);
33a033630e805c407080221e20b236b6054f324670Raph Levien}
34a033630e805c407080221e20b236b6054f324670Raph Levien
351fc0fa87d42ce9268ece76b85b9edc834593e53aRaph Levienstatic void MinikinFontSkia_SetSkiaPaint(const MinikinFont* font, SkPaint* skPaint, const MinikinPaint& paint) {
361a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    skPaint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
371a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    skPaint->setTextSize(paint.size);
38e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien    skPaint->setTextScaleX(paint.scaleX);
39e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien    skPaint->setTextSkewX(paint.skewX);
40e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien    MinikinFontSkia::unpackPaintFlags(skPaint, paint.paintFlags);
411fc0fa87d42ce9268ece76b85b9edc834593e53aRaph Levien    // Apply font fakery on top of user-supplied flags.
421fc0fa87d42ce9268ece76b85b9edc834593e53aRaph Levien    MinikinFontSkia::populateSkPaint(skPaint, font, paint.fakery);
431a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien}
441a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
45a033630e805c407080221e20b236b6054f324670Raph Levienfloat MinikinFontSkia::GetHorizontalAdvance(uint32_t glyph_id,
46a033630e805c407080221e20b236b6054f324670Raph Levien    const MinikinPaint &paint) const {
471a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    SkPaint skPaint;
48a033630e805c407080221e20b236b6054f324670Raph Levien    uint16_t glyph16 = glyph_id;
49a033630e805c407080221e20b236b6054f324670Raph Levien    SkScalar skWidth;
501fc0fa87d42ce9268ece76b85b9edc834593e53aRaph Levien    MinikinFontSkia_SetSkiaPaint(this, &skPaint, paint);
511a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    skPaint.getTextWidths(&glyph16, sizeof(glyph16), &skWidth, NULL);
529d9ee3d666c63938311839002ec974673998c6d0Raph Levien#ifdef VERBOSE
531a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    ALOGD("width for typeface %d glyph %d = %f", mTypeface->uniqueID(), glyph_id, skWidth);
549d9ee3d666c63938311839002ec974673998c6d0Raph Levien#endif
551a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    return skWidth;
561a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien}
571a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
581a73f732f91e97c9c66b808c245ddda36a10e987Raph Levienvoid MinikinFontSkia::GetBounds(MinikinRect* bounds, uint32_t glyph_id,
591a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    const MinikinPaint& paint) const {
601a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    SkPaint skPaint;
611a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    uint16_t glyph16 = glyph_id;
62a033630e805c407080221e20b236b6054f324670Raph Levien    SkRect skBounds;
631fc0fa87d42ce9268ece76b85b9edc834593e53aRaph Levien    MinikinFontSkia_SetSkiaPaint(this, &skPaint, paint);
641a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    skPaint.getTextWidths(&glyph16, sizeof(glyph16), NULL, &skBounds);
651a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    bounds->mLeft = skBounds.fLeft;
661a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    bounds->mTop = skBounds.fTop;
671a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    bounds->mRight = skBounds.fRight;
681a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    bounds->mBottom = skBounds.fBottom;
69a033630e805c407080221e20b236b6054f324670Raph Levien}
70a033630e805c407080221e20b236b6054f324670Raph Levien
71296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levienconst void* MinikinFontSkia::GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy) {
72296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien    // we don't have a buffer to the font data, copy to own buffer
73296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien    const size_t tableSize = mTypeface->getTableSize(tag);
74296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien    *size = tableSize;
75296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien    if (tableSize == 0) {
76296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien        return nullptr;
77a033630e805c407080221e20b236b6054f324670Raph Levien    }
78296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien    void* buf = malloc(tableSize);
79296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien    if (buf == nullptr) {
80296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien        return nullptr;
81296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien    }
82296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien    mTypeface->getTableData(tag, 0, tableSize, buf);
83296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien    *destroy = free;
84296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien    return buf;
85a033630e805c407080221e20b236b6054f324670Raph Levien}
86a033630e805c407080221e20b236b6054f324670Raph Levien
871fc0fa87d42ce9268ece76b85b9edc834593e53aRaph LevienSkTypeface *MinikinFontSkia::GetSkTypeface() const {
88a033630e805c407080221e20b236b6054f324670Raph Levien    return mTypeface;
89a033630e805c407080221e20b236b6054f324670Raph Levien}
90a033630e805c407080221e20b236b6054f324670Raph Levien
91296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levienconst void* MinikinFontSkia::GetFontData() const {
92296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien    return mFontData;
93296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien}
94296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien
95296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Leviensize_t MinikinFontSkia::GetFontSize() const {
96296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien    return mFontSize;
97296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien}
98296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien
99296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levienint MinikinFontSkia::GetFontIndex() const {
100296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien    return mTtcIndex;
101296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien}
102296bf8c55aaba0025f3e5b904fda3b6e15686753Raph Levien
103e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levienuint32_t MinikinFontSkia::packPaintFlags(const SkPaint* paint) {
104e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien    uint32_t flags = paint->getFlags();
105e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien    SkPaint::Hinting hinting = paint->getHinting();
106e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien    // select only flags that might affect text layout
107e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien    flags &= (SkPaint::kAntiAlias_Flag | SkPaint::kFakeBoldText_Flag | SkPaint::kLinearText_Flag |
108e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien            SkPaint::kSubpixelText_Flag | SkPaint::kDevKernText_Flag |
109e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien            SkPaint::kEmbeddedBitmapText_Flag | SkPaint::kAutoHinting_Flag |
110e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien            SkPaint::kVerticalText_Flag);
111e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien    flags |= (hinting << 16);
112e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien    return flags;
113e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien}
114e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien
115e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levienvoid MinikinFontSkia::unpackPaintFlags(SkPaint* paint, uint32_t paintFlags) {
116e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien    paint->setFlags(paintFlags & SkPaint::kAllFlags);
117e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien    paint->setHinting(static_cast<SkPaint::Hinting>(paintFlags >> 16));
118e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien}
119e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien
1201fc0fa87d42ce9268ece76b85b9edc834593e53aRaph Levienvoid MinikinFontSkia::populateSkPaint(SkPaint* paint, const MinikinFont* font, FontFakery fakery) {
1211fc0fa87d42ce9268ece76b85b9edc834593e53aRaph Levien    paint->setTypeface(reinterpret_cast<const MinikinFontSkia*>(font)->GetSkTypeface());
1220627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien    paint->setFakeBoldText(paint->isFakeBoldText() || fakery.isFakeBold());
1230627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien    if (fakery.isFakeItalic()) {
1240627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien        paint->setTextSkewX(paint->getTextSkewX() - 0.25f);
1250627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien    }
1261fc0fa87d42ce9268ece76b85b9edc834593e53aRaph Levien}
1271fc0fa87d42ce9268ece76b85b9edc834593e53aRaph Levien
128a033630e805c407080221e20b236b6054f324670Raph Levien}
129