Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support glyphs #54

Merged
merged 36 commits into from
Aug 8, 2022
Merged

feat: support glyphs #54

merged 36 commits into from
Aug 8, 2022

Conversation

gmaclennan
Copy link
Member

@gmaclennan gmaclennan commented Aug 1, 2022

Closes #5

@achou11 here's a quick script to generate SDFs - just wanted to check it worked and start my Monday with something with a quick result :)

Copy link
Member

@achou11 achou11 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it works, I won't dispute that 😄 had a couple of small comments but otherwise seems safe to merge and use in a follow up

scripts/generate-sdf.js Show resolved Hide resolved

async function generateSdf({ font, outDir }) {
return new Promise((resolve, reject) => {
for (let i = 0; i < 65536; i = i + 256) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for my own education, what are these numbers?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These number are character codes. The mapbox api expects SDFs to be served as combined files of 256 glyphs (see the API details). For ASCII the map only needs to request the 0-255.pbf, but when the client library (mapbox-gl-js) comes across labels with other characters, it downloads the glyph ranges needed to render those characters.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah I see. maybe worth putting a link to the docs here but thanks for explaining!

@achou11
Copy link
Member

achou11 commented Aug 1, 2022

just noticed ci failed and that's because fontnik doesn't support node 16. not necessarily blocking since it's only being used as a dev dependency, but worth noting before merging

@achou11 achou11 self-requested a review August 1, 2022 15:48
@achou11 achou11 marked this pull request as ready for review August 3, 2022 20:55
@achou11
Copy link
Member

achou11 commented Aug 3, 2022

@gmaclennan marked as ready for review. probably missing a few key tests and some refinements, but think it's ready to be glanced at

Comment on lines +64 to +69
export const createForwardedUpstreamError = (statusCode: number) =>
createError(
`FORWARDED_UPSTREAM_${statusCode}`,
'Upstream request at %s responded with: %s',
statusCode
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There may be a better way of approaching and/or naming this, but the idea is to be able to forward errors that we receive from upstream endpoints

@@ -27,7 +27,7 @@ export const MismatchedIdError = createError(
export const MBAccessTokenRequiredError = createError(
'FST_ACCESS_TOKEN',
'A Mapbox API access token is required for styles that use Mapbox-hosted sources',
400
401
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed this to match the status code used by Mapbox's API for errors related to the access token, which is consistent across their different resources

Comment on lines +26 to +27
// TODO: Use LRU for this?
function getStaticFile(font: string, start: number, end: number) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would using LRU help with this?

Comment on lines +64 to +65
// TODO: Change the kind of error thrown here?
if (!row) throw err
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

highlighting this


// 2. Offline attempt failed, but may be able to get upstream resource

// TODO: Validate that the glyphs url contains {fontstack} and {range} templates?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

highlighting this


// Returns an array of values where each value is a comma-separated string of font names
// Adapted version of https://github.com/digidem/mapbox-style-downloader/blob/695ed8a981efb9f0ece80cba8c81d075f9a0cdda/lib/glyphs.js#L21-L53
export function getFontStacks(style: StyleJSON): string[] {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not used at the moment

err instanceof NotFoundError ||
(err instanceof HTTPError && err.response.statusCode === 404)

// TODO: Do we want to return default fallback if upstream is not found?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

highlighting this

Comment on lines +75 to +81
// This is when the upstream api provides an error status
if (err instanceof HTTPError) {
throw new (createForwardedUpstreamError(err.response.statusCode))(
err.response.url,
err.response.statusMessage
)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems useful to forward the error response from the upstream api in this case - i'd imagine that the map client making these requests would expect an api similar to the mapbox one

Comment on lines +45 to +46
// TODO: Should we return always return the offline asset if it exists?
async getGlyphs({ styleId, accessToken, font, start, end }) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the approach implemented is:

  1. Find the matching offline asset.
    a. If it exists, attempt to return that static asset
    b. if it doesn't exist: go to step 2
  2. Fetch from upstream.
    a. if successful, return the response from upstream
    b. if not successful because:
    1. resource not found (404), attempt to return the fallback offline asset (Open Sans)
    2. some other other response error, forward that error

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thinking that we probably need to handle a case where we know we're offline and therefore should serve up the fallback offline asset at the very least

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see 13f0bf3 for offline handling. in this case we serve the default static asset

@achou11 achou11 mentioned this pull request Aug 8, 2022
6 tasks
@gmaclennan gmaclennan mentioned this pull request Aug 8, 2022
@achou11 achou11 merged commit c0d0231 into master Aug 8, 2022
@achou11 achou11 deleted the feat/glyphs branch August 8, 2022 17:20
@achou11 achou11 mentioned this pull request Aug 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add routes, api methods & e2e tests for Glyphs
2 participants